ListPopupWindow不服从WRAP_CONTENT宽度规格

我试图使用ListPopupWindow通过ArrayAdapter显示string列表(最终这将是一个更复杂的自定义适配器)。 代码如下。 如截图所示,生成的ListPopupWindow好像内容宽度为零。 它显示了正确的项目数量,项目仍然可以点击,点击成功生产Toast ,所以至less有这么多的工作正常。

一个有趣的笔记:我可以提供一个像素的宽度popup.setWidth(...)而不是ListPopupWindow.WRAP_CONTENT ,它会显示一些内容,但这似乎很不灵活。

我如何使ListPopupWindow包装其内容?

testing活动:

 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(); } } 

截图:

在这里输入图像说明

您可以测量适配器内容的宽度:

 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; } 

并在你的showPopup()函数中:

  ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, STRINGS); popup.setAdapter(arrayAdapter); popup.setAnchorView(anchorView); popup.setContentWidth(measureContentWidth(arrayAdapter)); 

问题是与ListPopupWindow的实现。 我检查了源代码,并使用setContentWidth(ListPopupWindow.WRAP_CONTENT)setWidth(ListPopupWindow.WRAP_CONTENT)使popup窗口使用其锚点视图的宽度。

我认为最好用的是PopupMenu。 例:

 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(); 

我只需在160dp左右的dimen.xml文件中设置一个维度即可:

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

然后使用getDimensionPixelSize方法设置您的popup窗口宽度以转换为像素:

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

这应该保持大小密度独立。

我相信你的问题在于你的ArrayAdapter使用simple_list_item_1。 如果您查看该元素的源代码,则它具有属性

 android:layout_width="match_parent" 

如果您在这里查看源代码,您可以使用相同的信息创build自己的new_list_item_1.xml,但将其更改为android:layout_width="wrap_content" ,然后在ArrayAdapter中使用它

实际上你可以得到anchorView的父元素(因为实际的anchorView通常是一个button)并且从那里开始你的宽度。 例如:

 popup.setWidth(((View)anchor.getParent()).getWidth()/2); 

这样你可以得到一个灵活的宽度。

listPopupWindow.setWidth(400);

listPopupWindow.setHeight(ListPopupWindow.WRAP_CONTENT);

另一个解决scheme是在你的布局xml中设置一个0dp高度的视图来作为一个锚点。

 <View android:id="@+id/popup_anchor" android:layout_width="140dp" android:layout_height="0dp"/> 

然后在调用show()方法之前设置锚点视图。

 listPopupWindow.setAnchorView(popupAnchor); listPopupWindow.show();