web-dev-qa-db-fra.com

ListPopupWindow n'obéissant pas à la spécification de largeur WRAP_CONTENT

J'essaie d'utiliser ListPopupWindow pour afficher une liste de chaînes via un ArrayAdapter (il s'agira éventuellement d'un adaptateur personnalisé plus complexe). Le code est ci-dessous. Comme le montre la capture d'écran, la ListPopupWindow résultante semble agir comme si la largeur du contenu était égale à zéro. Il indique le nombre approprié d'éléments, les éléments sont toujours cliquables et un clic réussi permet de générer une Toast, de sorte qu'au moins ce nombre fonctionne correctement. 

Une note intéressante: je pourrais fournir une largeur en pixels à popup.setWidth(...) au lieu de ListPopupWindow.WRAP_CONTENT et il affichera une partie du contenu, mais cela semble très rigide.

Comment puis-je faire en sorte que la ListPopupWindow enveloppe son contenu?

Activité de test:

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

capture d'écran:

enter image description here

36
Karakuri

Le problème vient de la mise en oeuvre de ListPopupWindow. J'ai vérifié le code source et l'utilisation de setContentWidth(ListPopupWindow.WRAP_CONTENT) ou setWidth(ListPopupWindow.WRAP_CONTENT) a pour effet que la fenêtre contextuelle utilise la largeur de sa vue d'ancrage.

23
Karakuri

Vous pouvez mesurer la largeur du contenu de l'adaptateur:

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

et dans votre fonction 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));
54
alerant

Je pense que la meilleure chose à utiliser est le PopupMenu. Exemple:

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
android developer

Je voudrais juste définir une dimension dans votre fichier dimen.xml à 160dp ou plus:

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

Définissez ensuite la largeur de votre popup à l'aide de la méthode getDimensionPixelSize pour la convertir en pixels:

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

Cela devrait garder la densité de taille indépendante.

4
JaredBanyard

Vous pouvez réellement obtenir le parent du anchorView (puisque le anchorView actuel est généralement un bouton) et baser votre largeur à partir de là. Par exemple:

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

De cette façon, vous pouvez obtenir une largeur flexible.

3
Caio L.

Je pense que votre problème réside dans votre ArrayAdapter utilisant simple_list_item_1. Si vous regardez le code source de cet élément, il a la propriété de 

Android:layout_width="match_parent"

Si vous regardez la source ici , vous pouvez créer votre propre new_list_item_1.xml avec les mêmes informations mais en le changeant en Android:layout_width="wrap_content" et l’utiliser ensuite dans votre ArrayAdapter.

3
Mike

Une autre solution consiste à définir une vue de hauteur 0dp dans votre XML de mise en page à utiliser comme ancre.

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

puis définissez la vue d'ancrage avant d'appeler la méthode show ().

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

Ce qui suit peut aider.

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