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:
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));
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.
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With