我正在尝试使用ListPopupWindow通过ArrayAdapter
显示字符串列表(最终这将是一个更复杂的自定义适配器)。代码如下。如屏幕截图所示,生成的ListPopupWindow
似乎就像内容宽度为零一样。它会显示正确数量的项目,这些项目仍然可以点击,并且点击成功生成Toast
,因此至少可以正常工作。
一个有趣的说明:我可以提供popup.setWidth(...)
而不是ListPopupWindow.WRAP_CONTENT
的宽度(以像素为单位),它会显示一些内容,但这似乎非常不灵活。
如何让ListPopupWindow
包装其内容?
测试活动:
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();
}
}
截图:
答案 0 :(得分:54)
您可以测量适配器内容的宽度:
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));
答案 1 :(得分:24)
问题在于ListPopupWindow
的实施。我检查了源代码,并使用setContentWidth(ListPopupWindow.WRAP_CONTENT)
或setWidth(ListPopupWindow.WRAP_CONTENT)
使弹出窗口使用其锚视图的宽度。
答案 2 :(得分:6)
我认为最好用的是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();
答案 3 :(得分:4)
我只想在你的dimen.xml文件中设置160dp左右的维度:
<dimen name="overflow_width">160dp</dimen>
然后使用getDimensionPixelSize方法设置弹出窗口宽度以转换为像素:
int width = mContext.getResources().getDimensionPixelSize(R.dimen.overflow_width);
mListPopupWindow.setWidth(width);
这应该保持尺寸密度独立。
答案 4 :(得分:3)
我相信你的问题在于使用simple_list_item_1的ArrayAdapter。如果查看该元素的源代码,则它具有
的属性android:layout_width="match_parent"
如果查看源here,您可以使用相同的信息创建自己的new_list_item_1.xml,但将其更改为android:layout_width="wrap_content"
,然后在ArrayAdapter中使用
答案 5 :(得分:3)
你实际上可以获得anchorView的父级(因为实际的anchorView通常是一个按钮)并且从那里开始你的宽度。例如:
popup.setWidth(((View)anchor.getParent()).getWidth()/2);
这样你就可以获得灵活的宽度。
答案 6 :(得分:0)
以下内容可以提供帮助;
1.5.1.RELEASE
答案 7 :(得分:0)
另一种解决方案是在布局xml中设置0dp高度视图以用作锚点。
<View
android:id="@+id/popup_anchor"
android:layout_width="140dp"
android:layout_height="0dp"/>
然后在调用show()方法之前的某个时候设置锚视图。
listPopupWindow.setAnchorView(popupAnchor);
listPopupWindow.show();
答案 8 :(得分:0)
我的方法。
在您的布局中创建一个 View
作为锚点,具有您的专用宽度和位置(高度 1 dp,您希望宽度)(可能是动态的,即使用 ConstraintLayouts)。使其不可见 (android:visibility=View.INIVISIBLE
)。
<View
android:id="@+id/my_anchor"
android:layout_height="1dp"
android:layout_width="0dp"
app:layout_constraintTop_toBottomOf="@id/list_item_order_list_app_compat_image_button_gallery"
app:layout_constraintStart_toEndOf="@id/list_item_order_list_material_button_map"
app:layout_constraintEnd_toEndOf="parent"
android:visibility="invisible"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
/>
在您的 viewAnchor
中引用此视图(即使用绑定):
listPopupWindow.anchorView = binding.myAnchor