wrap_content for a listview's width
Asked Answered
I

2

16

Is there a way to have a ListView with the with equal to the longest row? Setting wrap_content for the ListView 's width has no effect. The ListView covers the whole screen horizontally.

This is the activity layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ListView   android:id="@+id/listview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/country_picker_bg" />

and this is the row xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:layout_marginBottom="@dimen/padding"
    android:padding="@dimen/padding"
    android:background="@drawable/white_round_rect" >
    <TextView android:id="@+id/title"
        style="@style/GreyTextView"
        android:layout_marginLeft="@dimen/padding"/>    
    <ImageView  
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:src="@drawable/orange_arrow_selector"/>
</LinearLayout>

Thank you, Gratzi

Insupportable answered 1/7, 2011 at 11:8 Comment(4)
Can you please be more specific? I've tried to create a custom listview and to set the width in the onMeasure method, but nothing happened.Insupportable
post your xml as well as add further details in your question.Breathed
check your all drawable background size(for ListView and TextView).Do you getting any exception? I think you have to add android:layout_width proprty to TextView. what is value of @dimen/padding in android:layout_marginLeft="@dimen/padding?Breathed
The text view's width is set in the style. I has nothing to do with the rows. The rows are not full screen width, only the listview is.Insupportable
W
15

Is there a way to have a ListView with the with equal to the longest row?

No, in part because we have no way to know what the longest row is.

Let's say that you attach a ListAdapter to the ListView, where getCount() on the ListAdapter returns a value of 1,234,567. To determine the width of the longest row, we would have to create each row and examine its width. This would take hours, and the user will not be happy during those hours.

Watereddown answered 1/7, 2011 at 12:16 Comment(3)
Thanks for the reply. That makes sense. I have one more question related to this: is it a good practice to create a custom listview with the width equal to the background's drawable width? If it is, how can I do that? Setting the width in onMeasure() had no effect.Insupportable
@Gratzi: "is it a good practice to create a custom listview with the width equal to the background's drawable width?" -- usually, you make the background drawable resizeable (e.g., nine-patch PNG or ShapeDrawable), and design the ListView size around the actual data being presented in the list. The data is what the user will care about, much more than your background.Watereddown
@Gratzi: Making a ListView size be dependent on the size of a background image is not a good practice in general.Watereddown
B
38

Sometimes, you know there will always be a limited number of items, maybe 5, maybe 40. In those times you still want to use a ListView and you still want to wrap content.

For those times there is this method:

/**
 * Computes the widest view in an adapter, best used when you need to wrap_content on a ListView, please be careful
 * and don't use it on an adapter that is extremely numerous in items or it will take a long time.
 *
 * @param context Some context
 * @param adapter The adapter to process
 * @return The pixel width of the widest View
 */
public static int getWidestView(Context context, Adapter adapter) {
    int maxWidth = 0;
    View view = null;
    FrameLayout fakeParent = new FrameLayout(context);
    for (int i=0, count=adapter.getCount(); i<count; i++) {
        view = adapter.getView(i, view, fakeParent);
        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        int width = view.getMeasuredWidth();
        if (width > maxWidth) {
            maxWidth = width;
        }
    }
    return maxWidth;
}

Use it like so (notice I added some extra space to the width just in case):

listView.getLayoutParams().width = getWidestView(mContext, adapter)*1.05;
Broth answered 19/12, 2012 at 19:29 Comment(5)
This solution worked perfectly in a fragment-based app that I have. On a ListView with 15 items, System.currentTimeMillis() showed that the ListView could be resized to the optimal width in 6 milliseconds.Gaiter
Android should do this and give it as an option to the developers. Actually I assumed the option was "wrap_content", but actually it's not.Beatify
Strike! Great answer. Thanks a lot.Albertinealbertite
for what *1.05 is?Shoop
@Shoop The 1.05 is not required, I added it for good luck (absolutely no real reason).Broth
W
15

Is there a way to have a ListView with the with equal to the longest row?

No, in part because we have no way to know what the longest row is.

Let's say that you attach a ListAdapter to the ListView, where getCount() on the ListAdapter returns a value of 1,234,567. To determine the width of the longest row, we would have to create each row and examine its width. This would take hours, and the user will not be happy during those hours.

Watereddown answered 1/7, 2011 at 12:16 Comment(3)
Thanks for the reply. That makes sense. I have one more question related to this: is it a good practice to create a custom listview with the width equal to the background's drawable width? If it is, how can I do that? Setting the width in onMeasure() had no effect.Insupportable
@Gratzi: "is it a good practice to create a custom listview with the width equal to the background's drawable width?" -- usually, you make the background drawable resizeable (e.g., nine-patch PNG or ShapeDrawable), and design the ListView size around the actual data being presented in the list. The data is what the user will care about, much more than your background.Watereddown
@Gratzi: Making a ListView size be dependent on the size of a background image is not a good practice in general.Watereddown

© 2022 - 2024 — McMap. All rights reserved.