Search code examples
androidandroid-layoutlistviewandroid-relativelayout

Why does relative layout in listview not expand correctly with content when font is huge


I have a list view that for each item needs to display an image, a book title, the author and the price. Under normal circumstances my output is fine and looks like the following

enter image description here

My client has a large portion of customers that need to set the font size to huge. When this is done and the authors name is very long my output looks like below

enter image description here

This is not right and I would like it to look like this instead

enter image description here

In other words the height of list view and elements inside grow to fit larger amounts of text.

Here is the code which replicates my problem.

The book class

public class Book {
    public String name;
    public String author;
    public String price;

    public  Book(String name, String author, String price){
        this.name = name;
        this.author = author;
        this.price = price;
    }
}

The main activity code

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.list);

        ArrayList<Book> bookList = new ArrayList<Book>();
        bookList.add(new Book("Book 1", "By Christopher Christopheson",       "£0.50"));
        bookList.add(new Book("Book 2", "Author 2", "£0.75"));
        BookAdapter adapter = new BookAdapter(this, R.layout.row, bookList);

        listView.setAdapter(adapter);
    }
}

The book list view adapter

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import java.util.ArrayList;
import android.widget.TextView;


public class BookAdapter extends ArrayAdapter<Book> {

    private ArrayList<Book> items;   
    private LayoutInflater lInflater;

    public BookAdapter(Context context, int textViewResourceId, ArrayList<Book> items){
        super(context, textViewResourceId, items);
        lInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.items = items;     
    }

     @Override
    public View getView(int position, View convertView,   ViewGroup parent){
        View v = convertView;

        if(v == null){
            v = lInflater.inflate(R.layout.row, null);
        }
        Book b = items.get(position);

        if(b!= null){
            TextView bookName = (TextView)v.findViewById(R.id.book_name);
            TextView bookPrice = (TextView)v.findViewById(R.id.book_price);
            TextView bookAuthor =   (TextView)v.findViewById(R.id.book_author);

            if(bookName != null){
                bookName.setText(b.name);
            }

            if(bookPrice != null){
                bookPrice.setText(b.price);
            }

            if(bookAuthor != null){
                bookAuthor.setText(b.author);
            }
        }

        return v;

    }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="barnetttabs.com.basiclistview.MainActivity">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/list"
            android:layout_height="wrap_content"
            android:layout_width="match_parent">
        </ListView>
    </LinearLayout>

</android.support.constraint.ConstraintLayout>

row.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="150dp"
    android:paddingTop="4dp"
    android:paddingBottom="4dp"
    >

    <TextView
        android:id="@+id/price_background"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:minHeight="150dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:background="#0000ff"
        />

    <TextView
        android:id="@+id/book_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:minHeight="150dp"
        android:layout_toLeftOf="@id/price_background"
        android:layout_alignParentLeft="true"
        android:gravity="top"
        android:background="#d3d3d3"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:paddingLeft="110dp"
        android:paddingRight="4dp"
        />

   <ImageView
        android:id="@+id/book_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:src="@drawable/lvplaceholderimage"
    />



    <TextView
        android:id="@+id/book_price"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/book_image"
        android:textSize="17sp"
        android:layout_alignLeft="@id/price_background"
        android:layout_alignParentRight="true"
        android:textColor="#fff"
        android:paddingLeft="4dp"
        android:paddingRight="4dp"
        android:paddingTop="4dp"
        />

    <TextView
        android:id="@+id/book_author"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_alignLeft="@id/price_background"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_below="@id/book_price"
        android:paddingLeft="4dp"
        android:paddingRight="4dp"
        android:paddingBottom="4dp"
        />

</RelativeLayout>

I've tried fixing the layout_height of the relative layout in row.xml. This keeps the height consistent but when the author is too long some of the text is hidden. When I've searched for solutions on this most things say the solution is to set height as wrap_content which I have done but it doesn't the problem.

Is there a way to fix this through either changing the xml layout or the java code? Maybe the relative layout I've used here in row.xml is not the right approach?


Solution

  • Chetan's suggestion was the way to go. The basic idea is to change from a relative layout to a horizontal linear layout. The middle portion is given weight 0 and the 2 end bits have their lengths set as before. The only drawback is the method needs to have a nested layout to get the blue bit to work but hopefully not too much of a performance hit.

    In activity_main.xml change the listview code to

      <ListView
            android:id="@+id/list"
            android:layout_height="wrap_content"
            android:divider="@android:color/transparent"
            android:dividerHeight="5.0sp"
            android:layout_width="match_parent">
        </ListView>
    

    Change row.xml to

    <?xml version="1.0" encoding="utf-8"?>
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="150dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:orientation="horizontal"
        android:background="#d3d3d3"
        >
    
        <ImageView
            android:id="@+id/book_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/lvplaceholderimage"
            android:layout_gravity="top"
            />
    
        <TextView
            android:id="@+id/book_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:textSize="17sp"
            android:layout_gravity="top"
            android:paddingLeft="4dp"
            android:paddingRight="4dp"
            android:layout_weight="1"
            />
    
        <RelativeLayout
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:minHeight="150dp"
            android:background="#0000ff">
    
            <TextView
                android:id="@+id/book_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="17sp"
                android:layout_alignParentTop="true"
                android:textColor="#fff"
                android:paddingLeft="4dp"
                android:paddingRight="4dp"
                android:paddingTop="4dp"
                />
    
            <TextView
                android:id="@+id/book_author"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="17sp"
                android:layout_below="@id/book_price"
                android:layout_alignParentBottom="true"
                android:paddingLeft="4dp"
                android:paddingRight="4dp"
                android:paddingBottom="4dp"
                 />
        </RelativeLayout>
    </LinearLayout>
    

    Then it looks like this enter image description here