Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListPopupWindow not obeying WRAP_CONTENT width spec

I'm trying to use ListPopupWindow to show a list of strings via an ArrayAdapter (eventually this will be a more complex custom adapter). Code is below. As shown in the screenshot, the resulting ListPopupWindow seems to act as if the content width is zero. It shows the proper number of items, the items are still clickable, and clicking successfully produce a Toast, so at least that much is working properly.

An interesting note: I could supply a width in pixels to popup.setWidth(...) instead of ListPopupWindow.WRAP_CONTENT and it will show some of the content, but this seems very inflexible.

How do I make the ListPopupWindow wrap its content?

Test activity:

public class MainActivity extends Activity {

    private static final String[] STRINGS = {"Option1","Option2","Option3","Option4"};
    private View anchorView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getActionBar().setHomeButtonEnabled(true);
        setContentView(R.layout.activity_main);
        anchorView = findViewById(android.R.id.home);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                showPopup();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void showPopup() {
        ListPopupWindow popup = new ListPopupWindow(this);
        popup.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, STRINGS));
        popup.setAnchorView(anchorView);
        popup.setWidth(ListPopupWindow.WRAP_CONTENT);
        popup.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, "Clicked item " + position, Toast.LENGTH_SHORT).show();
            }
        });
        popup.show();
    }
}

screenshot:

enter image description here

like image 814
Karakuri Avatar asked Jan 07 '13 17:01

Karakuri


4 Answers

You could measure the width of the adapter content:

private int measureContentWidth(ListAdapter listAdapter) {
    ViewGroup mMeasureParent = null;
    int maxWidth = 0;
    View itemView = null;
    int itemType = 0;

    final ListAdapter adapter = listAdapter;
    final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    final int count = adapter.getCount();
    for (int i = 0; i < count; i++) {
        final int positionType = adapter.getItemViewType(i);
        if (positionType != itemType) {
            itemType = positionType;
            itemView = null;
        }

        if (mMeasureParent == null) {
            mMeasureParent = new FrameLayout(mContext);
        }

        itemView = adapter.getView(i, itemView, mMeasureParent);
        itemView.measure(widthMeasureSpec, heightMeasureSpec);

        final int itemWidth = itemView.getMeasuredWidth();

        if (itemWidth > maxWidth) {
            maxWidth = itemWidth;
        }
    }

    return maxWidth;
}

and in your showPopup() function:

 ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, STRINGS);
    popup.setAdapter(arrayAdapter);
    popup.setAnchorView(anchorView);
    popup.setContentWidth(measureContentWidth(arrayAdapter));
like image 54
alerant Avatar answered Oct 21 '22 02:10

alerant


The problem is with the implementation of ListPopupWindow. I checked the source code, and using setContentWidth(ListPopupWindow.WRAP_CONTENT) or setWidth(ListPopupWindow.WRAP_CONTENT) makes the popup window use the width of its anchor view instead.

like image 42
Karakuri Avatar answered Oct 21 '22 02:10

Karakuri


I think the best thing to use is the PopupMenu . example:

final PopupMenu popupMenu = new PopupMenu(mActivity, v);
popupMenu.getMenu().add("test");
popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {

    @Override
    public boolean onMenuItemClick(final MenuItem item) {
        return true;
    }
});
popupMenu.show();
like image 7
android developer Avatar answered Oct 21 '22 02:10

android developer


I would just set a dimension in your dimen.xml file at 160dp or so:

<dimen name="overflow_width">160dp</dimen>

Then set your popup width using the getDimensionPixelSize method to convert into pixels:

int width = mContext.getResources().getDimensionPixelSize(R.dimen.overflow_width); 
mListPopupWindow.setWidth(width);

That should keep the size density independent.

like image 5
JaredBanyard Avatar answered Oct 21 '22 03:10

JaredBanyard