Ich versuche, ListPopupWindow zu verwenden, um eine Liste von Zeichenfolgen über eine ArrayAdapter
anzuzeigen (eventuell wird dies ein komplexerer benutzerdefinierter Adapter). Code ist unten. Wie im Screenshot gezeigt, scheint die resultierende ListPopupWindow
so zu wirken, als ob die Breite des Inhalts null wäre. Es zeigt die richtige Anzahl von Elementen an, die Elemente sind weiterhin anklickbar. Wenn Sie erfolgreich klicken, wird eine Toast
erzeugt, sodass zumindest so viel ordnungsgemäß funktioniert.
Eine interessante Anmerkung: Ich könnte popup.setWidth(...)
anstelle von ListPopupWindow.WRAP_CONTENT
eine Breite in Pixel angeben, und es wird ein Teil des Inhalts angezeigt. Dies scheint jedoch sehr unflexibel zu sein.
Wie lasse ich die ListPopupWindow
den Inhalt einwickeln?
Testaktivität:
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();
}
}
Bildschirmfoto:
Das Problem liegt bei der Implementierung von ListPopupWindow
. Ich habe den Quellcode überprüft, und mithilfe von setContentWidth(ListPopupWindow.WRAP_CONTENT)
oder setWidth(ListPopupWindow.WRAP_CONTENT)
verwendet das Popup-Fenster stattdessen die Breite der Ankeransicht.
Sie können die Breite des Adapterinhalts messen:
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;
}
und in Ihrer showPopup () - Funktion:
ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this, Android.R.layout.simple_list_item_1, STRINGS);
popup.setAdapter(arrayAdapter);
popup.setAnchorView(anchorView);
popup.setContentWidth(measureContentWidth(arrayAdapter));
Ich denke, das Beste ist das PopupMenu. Beispiel:
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();
Ich würde einfach eine Dimension in Ihrer dimen.xml-Datei bei 160dp oder so festlegen:
<dimen name="overflow_width">160dp</dimen>
Legen Sie dann die Popup-Breite mit der Methode getDimensionPixelSize fest, um sie in Pixel umzuwandeln:
int width = mContext.getResources().getDimensionPixelSize(R.dimen.overflow_width);
mListPopupWindow.setWidth(width);
Das sollte die Größendichte unabhängig halten.
Sie können tatsächlich das übergeordnete Element von anchorView abrufen (da es sich bei dem eigentlichen AnkerView im Allgemeinen um eine Schaltfläche handelt) und von dort aus Ihre Breite bestimmen. Zum Beispiel:
popup.setWidth(((View)anchor.getParent()).getWidth()/2);
Auf diese Weise erhalten Sie eine flexible Breite.
Ich glaube, Ihr Problem liegt bei Ihrem ArrayAdapter mit simple_list_item_1. Wenn Sie sich den Quellcode für dieses Element ansehen, hat es die Eigenschaft
Android:layout_width="match_parent"
Wenn Sie sich die Quelle here anschauen, können Sie Ihre eigene neue_list_item_1.xml mit denselben Informationen erstellen, jedoch in Android:layout_width="wrap_content"
ändern und diese dann in Ihrem ArrayAdapter verwenden
Eine andere Lösung besteht darin, eine 0dp-Höhenansicht in Ihrer Layout-XML festzulegen, die als Anker verwendet werden soll.
<View
Android:id="@+id/popup_anchor"
Android:layout_width="140dp"
Android:layout_height="0dp"/>
legen Sie dann die Ankeransicht fest, bevor Sie die show () -Methode aufrufen.
listPopupWindow.setAnchorView(popupAnchor);
listPopupWindow.show();
Folgendes kann helfen;
listPopupWindow.setWidth(400);
listPopupWindow.setHeight(ListPopupWindow.WRAP_CONTENT);