web-dev-qa-db-de.com

ListPopupWindow entspricht nicht der WRAP_CONTENT-Breitenangabe

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:

enter image description here

36
Karakuri

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.

23
Karakuri

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));
54
alerant

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

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.

4
JaredBanyard

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.

3
Caio L.

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

3
Mike

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

Folgendes kann helfen;

listPopupWindow.setWidth(400);
listPopupWindow.setHeight(ListPopupWindow.WRAP_CONTENT);
0
Pankaj Sharma