Android: listview array adapter not wrapping conte

2019-09-08 16:04发布

问题:

I have a Theme.Dialog activity that presents a list of devices to a user. the activity uses a ListView with a dynamically created ArrayAdapter to display the list of devices. For some reason however, the ListView (and thus the activity itself) isn't resizing to wrap it's content correctly. Instead, it acts as if it's got a set width of about half the screen (and this persists across devices with different screen sizes). I can't for the life of my figure out where this is set, though.

Can anyone see what I'm missing? (I've tried to strip the irrelevent bits out of the following code)

Here's my activity:

public class DeviceListActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Setup the window
        setContentView(R.layout.device_list);

        // Initialize array adapters
        mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);

        // Find and set up the ListView for paired devices
        ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
        pairedListView.setAdapter(mPairedDevicesArrayAdapter);

        //the following doesn't do anything
        //getWindow().setLayout(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        mPairedDevicesArrayAdapter.add("asdfasdfa");        

    }
}

Here is device_list.xml:

<?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="fill_parent"
    android:orientation="vertical" >


    <ListView
        android:id="@id/paired_devices"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:stackFromBottom="true" 
        android:background="#0000FF"/>
        <!-- the colour shows the listview stretching wider than the text it contains -->


</LinearLayout>

Here's the relevant portion of my AndroidManifest.xml:

<activity
     android:name=".DeviceListActivity"
     android:configChanges="keyboardHidden|orientation"
     android:label="too wide"
     android:theme="@android:style/Theme.Dialog">
</activity>

And here's device_name.xml (which is used to initialize the ArrayAdapter:

<?xml version="1.0" encoding="UTF-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="5.0dip"
    android:textSize="18.0sp" />

And if you've stuck with reading the question until now, I'm grateful already.

Here's the end result (with the rest of my app in the background):

回答1:

I realize that this is essentially a closed question but I believe that by setting windowIsFloating to true in a theme as seen in this answer https://stackoverflow.com/a/8876358 your problem will be fixed.



回答2:

I'm pretty sure it is because of the android:theme="@android:style/Theme.Dialog", those pesky dialogs with their own width and height.

Try the following: Create a Fragment that represents your ListActivity as a Listview. Placing this over your other Fragments creates a dialog-like behavior.

I'm 100% sure the problem is the Theme.Dialog. Your best shot would be changing your strategy for displaying that list. (Using Fragments, for example)



回答3:

i was finally able to get this to work ..i subclassed Listview and changed how it measured. It seems the listview natively will measure just the first child. So it uses the width of the first child. I changed it to search the listviews children for the widest row.

so your xml for the dialog content would look like this:

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

<com.mypackage.myListView
    android:id="@+id/lv"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
 />

and the myListView would look like this:

public class MyListView extends ListView{

public MyListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    int maxWidth = meathureWidthByChilds() + getPaddingLeft() + getPaddingRight();
    super.onMeasure(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.EXACTLY), heightMeasureSpec);     
}


 public int meathureWidthByChilds() {
    int maxWidth = 0;
    View view = null;
    for (int i = 0; i < getAdapter().getCount(); i++) {
        view = getAdapter().getView(i, view, this);
        //this measures the view before its rendered with no constraints from parent
        view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
        if (view.getMeasuredWidth() > maxWidth){
            maxWidth = view.getMeasuredWidth();
        }
    }
    return maxWidth;
 }
}