Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dialog is too wide when it contains a ListView

I'm having a problem with the width of a dialog when it contains a ListView: the dialog always nearly fills the width of the screen. Here's an example of the problem:

overly wide dialog

I need the dialog width to match the icons. I've tried fixing this by playing with dialog styles as described here and here, to no avail. I think those threads are on the wrong track (at least for this problem), because (1) they don't solve the problem and (2) I can get the dialog to size as desired by simply not using a ListView. For instance, if I replace the ListView with a simple TextView (details below), everything sizes as desired:

compact dialog

Here's the code I'm using to display the dialog:

private void showDisplayStyleDialog(int id, int choices, int values) {
    final Dialog dlg = new Dialog(this);
    dlg.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dlg.setContentView(R.layout.display_style_dialog);
    final ListView lv = (ListView) dlg.findViewById(android.R.id.list);
    if (lv != null) {
        displayStyleAdapter.setChoices(choices, values);
        lv.setAdapter(displayStyleAdapter);
        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long itemId) {
                dlg.dismiss();
                setDisplayStyle(DisplayStyle
                        .valueOf(displayStyleAdapter.mValues[position]));
            }

        });
    }
    dlg.setCanceledOnTouchOutside(true);
    dlg.show();
}

I also tried creating the dialog using an AlertDialog.Builder, with no improvement. The dialog layout (display_style_dialog.xml) is:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/white" >
    </ListView>

</LinearLayout>

The adapter loads every row from this layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/holder"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="5dp" >

    <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/display_style_image_bg"
        android:contentDescription="@string/cd_display_style" />

</LinearLayout>

Examining the view hierarchy with the Android Debug Monitor reveals that only the ListView itself is the full width of the dialog; each row is (as desired) sized to match the icon width. It's the ListView itself that is forcing the wide dialog. If I change display_style_dialog.xml to:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/test_string"
        android:textColor="@android:color/black"
        android:background="@android:color/white" >
    </TextView>
</LinearLayout>

and make no other changes to code or resources, the result is the compact dialog shown above. As far as I can tell, the problem is strictly due to the presence of the ListView in the dialog.

I think I can work around this in the short term by placing a number of ImageViews in a VerticalLayout inside a ScrollView. Unfortunately, the arrangement and number of icons varies considerably according to the internal state of the app, so this is not a sustainable approach; in the long run, I really need to use a ListView. Any ideas on how to resolve this issue?

like image 307
Ted Hopp Avatar asked Aug 14 '13 03:08

Ted Hopp


2 Answers

First, sorry for my bad English, but I'll try my best to explain about my opinion.

ListView could contain any data(ex, string) which is short or long. So, if you set LayoutParams as a wrap_content, there is no way to know how long it is. Depends on data, actual data's width could be longer than screen's width.

So, if you set wrap_content, it will be automatically changed to match_parent/fill_parent(I don't know exactly but one of them)

You can see that also in height. ListView doesn't know how may rows should be drawn. So, in your case, ListView's height will be stretched up to Activity's height.

From Google I/O 2010, they explained why we shouldn't use wrap_content on ListView.

As I know, in your case(ListView's height is wrap_content), getView() will be called as many rows exist, when ListView is initialized.

So, my opinion is that you could set:

  1. exact width_value to Dialog, and set ListView's width to match_parent or fill_parent.

  2. ListView's width by x% of Activity's width.


Add, in your test, TextView in Dialog,

we can know exact width value by measuring text. So, It is possible to use wrap_content.

like image 188
Steven Avatar answered Sep 30 '22 03:09

Steven


I think you can fix this by making the Listview layout_width = 50sp. I mean something fix number instead of wrap_content.

like image 36
arshu Avatar answered Sep 30 '22 04:09

arshu