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
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
This is not right and I would like it to look like this instead
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?
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>