Android ListView fixed height item
Asked Answered
R

7

9

Got a little problem. I'd like to create an android list view activity with all items in the list having a fixed height.

So, my item layout (thread_item.xml) looks like this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="300dip"
        >
    <TextView android:id="@+id/thread_item_title"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="[dummy]"
              android:textSize="20dip"
              android:textStyle="bold"
            />
    <ImageView android:id="@+id/thread_first_image"
               android:layout_below="@id/thread_item_title"
               android:scaleType="centerInside"
               android:maxWidth="100dip"
               android:maxHeight="100dip"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:adjustViewBounds="true" />
    <TextView
            android:id="@+id/thread_item_preview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@id/thread_first_image"
            android:text="[dummy]"
            android:textSize="15dip">
    </TextView>
</RelativeLayout>

I set layout_height of the root element to 300dip and expect all items to have the same height, but they don't. When I run the application it looks like the height having a wrap_content value.

In addition the activity itself looks like this:

public class ThreadListActivity extends ListActivity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        /*
         Code to get items from the storage.
        */

        setListAdapter(new ThreadItemAdapter(this, R.layout.thread_item, itemsArray)));


        getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                /*Start new Activity. Unrelated stuff.*/
            }
        });
    }
}

And adapter I'm using looks like this:

public class ThreadItemAdapter extends ArrayAdapter<ThreadItem> {

    Activity context;
    List<ThreadItem> items;

    public ThreadItemAdapter(Activity context, int textViewResourceId, List<ThreadItem> items) {
        super(context, textViewResourceId, items);
        this.context = context;
        this.items = items;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inf = this.context.getLayoutInflater();
        View result;
        if (convertView == null) {
            result = inf.inflate(R.layout.thread_item, null);
        } else {
            result = convertView;
        }

        TextView tbTitle = (TextView) result.findViewById(R.id.thread_item_title);
        TextView tbPreview = (TextView) result.findViewById(R.id.thread_item_preview);
        ImageView ivFirstImage = (ImageView) result.findViewById(R.id.thread_first_image);

        ThreadItem item = items.get(position);

        tbTitle.setText(item.getThreadTitle());
        ivFirstImage.setImageBitmap(item.getFirstImage());

        SimpleLeadingMarginSpan span = new SimpleLeadingMarginSpan(item.getFirstImage() != null ? 5 : 0, 115); // TODO: const
        SpannableString previewText = new SpannableString(item.getThreadPreview());
        previewText.setSpan(span, 0, previewText.length(), 0);
        tbPreview.setText(previewText);

        return result;
    }
}

I can't see why all list items still wrap their content and don't stay 300dip in height. They might be both smaller or bigger then 300dip. I'm using android 2.3.3, testing on HTC Evo 3D device and an emulator (both show same result).

Thanks a lot in advance.

UPD:

Thanks to Miguel and Sam. The solution is to set maxHeight to the textView, that makes my list item grow (that would be +id/thread_item_preview) and setting the RelativeLayout's minHeight to 300dip as well, to prevent it from shrinking.

Ruffled answered 30/4, 2012 at 17:22 Comment(1)
If we set the min height and max height to be the same what would would happen when the size of the text in the list view is exceeds that height?Aeciospore
V
31

What if you change all the child view heights in the row from wrap_content to match_parent?


From comments

Have you tried the minHeight and maxHeight attributes? For example:

android:minHeight="300dp"

You should also watch Android's Romain Guy discuss efficiency in adapters and getView().

Veroniqueverras answered 30/4, 2012 at 17:30 Comment(5)
Nope, same result. The biggest textview id/thread_item_preview still kind of stretches RelativeLayout to be bigger and the layout itself still shrinks if content needs less then 300dips height. Anyhow, thank you for the suggestion.Ruffled
Hmph, have you tried the minHeight and maxHeight attributes?Veroniqueverras
Should've thought about that, thank you! Will post a solution in a moment.Ruffled
@Veroniqueverras : If we set the min height and max height to be the same what would would happen when the size of the text in the list view is exceeds that height?Aeciospore
This is a bad answer. the correct solution is to pass the parent to inflateCristobalcristobalite
K
42

when inflating for convertView, instead of just

result = inf.inflate(R.layout.thread_item, null);

do

result = inf.inflate(R.layout.thread_item, parent, false);

The method in question is inflater.inflate(int viewId, ViewGroup parent, boolean attachToRoot) -- because you're not honoring the supplied parent (which in this case is the ListView), whatever dimension you supply to the listview item will by default be set to layout_width=fill_parent, layout_height=wrap_content, ignoring the 300dip height you specified in xml. By supplying the parent view and passing false, the inflater will honor the 300dip height, while not attaching it to the root (parent).

Km answered 30/4, 2012 at 17:50 Comment(7)
Yeah, I've seen that kind of answer on stackoverflow before. But in my adapter's getView method parent is null for some reason.Ruffled
have you tried it? is it crashing when you use the overloaded inflate?Km
My bad, parent wasn't null, sorry for that. And looks like an overloaded version also works. Thank you.Ruffled
if i do like this, some items are not showing in the list view and the item place are changing. help meWhidah
@Wizard sounds like you have a different problem than OP's. Consider opening a new question if you can't find one here in SO.Km
@Km i found the solution at this link and thanks for the interest.Whidah
This is the correct solution. Further reading hereMaihem
V
31

What if you change all the child view heights in the row from wrap_content to match_parent?


From comments

Have you tried the minHeight and maxHeight attributes? For example:

android:minHeight="300dp"

You should also watch Android's Romain Guy discuss efficiency in adapters and getView().

Veroniqueverras answered 30/4, 2012 at 17:30 Comment(5)
Nope, same result. The biggest textview id/thread_item_preview still kind of stretches RelativeLayout to be bigger and the layout itself still shrinks if content needs less then 300dips height. Anyhow, thank you for the suggestion.Ruffled
Hmph, have you tried the minHeight and maxHeight attributes?Veroniqueverras
Should've thought about that, thank you! Will post a solution in a moment.Ruffled
@Veroniqueverras : If we set the min height and max height to be the same what would would happen when the size of the text in the list view is exceeds that height?Aeciospore
This is a bad answer. the correct solution is to pass the parent to inflateCristobalcristobalite
E
7

Try changing this

android:layout_height="300dip"

to

android:minHeight="300dip"

This worked for me using an ExpandableListView, so I suppose it will work for this case.

Eba answered 30/4, 2012 at 17:51 Comment(5)
Thank you, this resolves one of two problems - the shrinking list item, but not the growing one. Anyhow, +1.Ruffled
Great :) By the way, I think I made a typo. It is "android:minHeight", not "android:layout_minHeight".Spoilfive
Worked for me but I must mention that this answer should be used together with @Km answer i.e. using inflate(R.layout.thread_item, parent, false);Udometer
But these statements are equalTaeniacide
@RohanKandwal your edit to this question does not make any sense, please review itPreparation
F
2

You can achieve this by specifying the same dimension for Min and Max. This fixed my problem.

<ImageView
    android:id="@+id/appIconImageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginBottom="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="8dp"
    android:adjustViewBounds="true"
    android:maxHeight="50dp"
    android:maxWidth="50dp"
    android:minHeight="50dp"
    android:minWidth="50dp"
    android:src="@drawable/ic_launcher" />

enter image description here

Foil answered 10/8, 2014 at 17:26 Comment(0)
S
0

Try setting the content TextView's height to 0dp and then setting its layout_alignParentBottom to true.

Sail answered 30/4, 2012 at 17:46 Comment(1)
In this case textview collapses and no text is visible.Ruffled
H
0
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:minHeight="60dp"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center"
    android:weightSum="1"
    android:background="@color/main_color">

    <ImageView
        android:id="@+id/img_left_menu"
        android:layout_weight="0.4"
        android:focusable="false"
        android:maxHeight="50dp"
        android:maxWidth="50dp"
        android:minHeight="50dp"
        android:minWidth="50dp"
        android:layout_width="0dp"
        android:scaleType="centerInside"
        android:adjustViewBounds="true"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tx_left_menu"
        android:layout_width="0dp"
        android:textSize="18dp"
        android:layout_gravity="center_vertical"
        android:layout_weight="0.6"
        android:singleLine="true"
        android:layout_height="wrap_content"
        android:focusable="false"
        />
</LinearLayout>
Hemialgia answered 24/3, 2015 at 17:51 Comment(0)
P
0

If I'm not mistaken, the listView automatically modifies the LayoutParams of a custom view to wrap_content, wrap_content. However, the answers above are correct, if you set a minHeight or minWidth it will work brilliantly.

Paleobotany answered 9/7, 2015 at 12:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.