web-dev-qa-db-fra.com

Comment réaliser ce menu contextuel personnalisé avec Material Design Android?

Je souhaite créer un menu contextuel personnalisé du type Twitter sous Android, par exemple, avec élément et image, mais je ne sais pas quel composant est utilisé pour cela. 

Dans le site Web Material Design, Google présente cette solution . Je pense donc qu’il existe une solution native pour y parvenir.

enter image description here

J'ai essayé avec Menu contextuel , mais je ne trouve pas comment personnaliser la disposition de cette vue de cette manière.

25
lopez.mikhael

vous pouvez utiliser ListPopupWindow pour soumettre votre adaptateur personnalisé, via lequel vous pouvez contrôler la présentation de chaque ligne de la ListPopupWindow. Comme pour une PopupWindow normale, vous devez fournir une vue d'ancrage et appeler setContentWidth sur l'instance de ListPopupWindow, qui définit la largeur de la fenêtre contextuelle en fonction de la taille de son contenu. C'est un petit prix que vous devez payer, mais pour un petit jeu de données, ce n'est pas grave. J'ai cette méthode utilitaire pour récupérer la largeur maximale de la ligne:

public int measureContentWidth(ListAdapter adapter) {
    int maxWidth = 0;
    int count = adapter.getCount();
    final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    View itemView = null;
    for (int i = 0; i < count; i++) {
        itemView = adapter.getView(i, itemView, this);
        itemView.measure(widthMeasureSpec, heightMeasureSpec);
        maxWidth = Math.max(maxWidth, itemView.getMeasuredWidth());
    }
    return maxWidth;
}
25
Blackbelt

Il existe un widget appelé PopupMenu qui est essentiellement un menu ancré dans une vue spécifique. Un inconvénient est qu’il n’affiche pas les icônes par défaut.

Cependant, vous pouvez utiliser la réflexion et appeler setForceShowIcon pour les révéler. Le code dont vous avez besoin est:

  • Etant donné que PopupMenu est ancré dans une vue spécifique, votre élément ActionBar a un attribut actionLayout. Cette disposition (action_item.xml) peut être aussi simple que:

    <Button
        xmlns:Android="http://schemas.Android.com/apk/res/Android"
        style="?attr/actionButtonStyle"
        Android:layout_gravity="center"
        Android:text="Show popup"
        Android:textStyle="bold"
        Android:textSize="12sp"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"/>
    
  • ActionBar style de menu qui contient votre élément avec la disposition ci-dessus

    <menu
        xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <item
            Android:id="@+id/popup_item"
            Android:title="Show popup"
            Android:showAsAction="always"
            Android:actionLayout="@layout/action_item"/>
    </menu>
    
  • Votre popup_menu.xml, la disposition que vous allez gonfler pour votre PopupMenu

    <menu
        xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <item
            Android:id="@+id/item1"
            Android:title="Item1"
            Android:icon="@mipmap/ic_launcher"/>
    </menu>
    
  • Et enfin, code pour effectuer le gonflage quand un élément ActionBar est cliqué

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_add_item:
                PopupMenu popup = new PopupMenu(this, item.getActionView());
                MenuInflater inflater = popup.getMenuInflater();
                inflater.inflate(R.menu.popup_menu, popup.getMenu());
    
                // Use reflection to invoke setForceShowIcon
                try {
                    Field[] fields = popup.getClass().getDeclaredFields();
                    for (Field field : fields) {
                        if ("mPopup".equals(field.getName())) {
                            field.setAccessible(true);
                            Object menuPopupHelper = field.get(popup);
                            Class<?> classPopupHelper = Class
                                    .forName(menuPopupHelper.getClass().getName());
                            Method setForceIcons = classPopupHelper
                                    .getMethod("setForceShowIcon", boolean.class);
                            setForceIcons.invoke(menuPopupHelper, true);
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                popup.show();
                return true;
        }
    
        return super.onOptionsItemSelected(item);
    }
    

Notez que pour obtenir ce texte multiligne dans un menu, vous devez également utiliser une variable actionLayout pour vos éléments de menu contextuels.

3
Simas

Utilisez un fragment de liste contextuelle . La bonne chose à propos des fragments est que vous pouvez facilement les animerIntroduction au fragment )

Si vous souhaitez contrôler entièrement le contenu de la fenêtre contextuelle, consultez la section Fragment de la boîte de dialogue

3
Steven Mark Ford

J'ai le même problème. Mais finalement, j'ai trouvé avec ma propre solution que je vous partage mon code. J'espère que cela vous aidera. 

popupWindowDogs = popupWindowDogs();
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            // popupWindowDogs.showAsDropDown(v, -5, 0);
            popupWindowDogs().showAtLocation(v, Gravity.CENTER, 0, 0);
        }
    });
    // Detect touched area
    detector = new SimpleGestureFilter(this, this);

}

public PopupWindow popupWindowDogs()
{

    // initialize a pop up window type
    PopupWindow popupWindow = new PopupWindow(this);

    // the drop down list is a list view
    final ListView listView = new ListView(this);
    // set our adapter and pass our pop up window contents
    listView.setAdapter(dogsAdapter(popUpContents));
    // listView.setBackgroundColor(Color.DKGRAY);
    listView.setBackgroundResource(R.drawable.ss4);
    listView.setPadding(0, 0, 0, 10);
    listView.setDivider(null);
    try {

        listView.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                View c = listView.getChildAt(0);
                String cc = listView.getChildAt(0).toString();
                int scrolly = -c.getTop() + listView.getFirstVisiblePosition() * c.getHeight();
                /*
                 * Toast.makeText(getApplicationContext(), scrolly + "", Toast.LENGTH_SHORT)
                 * .show();
                 */}

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                    int totalItemCount) {

            }
        });
    } catch (Exception e) {
        Toast.makeText(getApplicationContext(), e.toString() + "", Toast.LENGTH_SHORT)
                .show();
    }
    listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View v, int arg2,
                long arg3) {
            try {

                // TODO Auto-generated method stub
                Context mContext = v.getContext();
                Swipetouch mainActivity = ((Swipetouch) mContext);
                // add some animation when a list item was clicked
                Animation fadeInAnimation = AnimationUtils.loadAnimation(v.getContext(),
                        Android.R.anim.fade_in);
                fadeInAnimation.setDuration(10);
                v.startAnimation(fadeInAnimation);
                // dismiss the pop up
                mainActivity.popupWindowDogs.dismiss();
                // get the text and set it as the button text
                String val = (String) arg0.getItemAtPosition(arg2);
                // Toast.makeText(mContext, val, Toast.LENGTH_SHORT).show();
                if (val.equals("Signup Now")) {
                    Intent ii = new Intent(getApplicationContext(), Registration.class);
                    startActivity(ii);
                    stopService(new Intent(Swipetouch.this, MyService.class));
                    stopService(new Intent(Swipetouch.this, MyService.class));
                } else if (val.equals("Login")) {
                    Intent ii = new Intent(getApplicationContext(), MyLoginActivity.class);
                    startActivity(ii);
                    stopService(new Intent(Swipetouch.this, MyService.class));

                } else if (val.equals("Exit")) {
                    finish();
                    stopService(new Intent(Swipetouch.this, MyService.class));
                } else if (val.equals("Friends")) {
                    Intent ii = new Intent(getApplicationContext(), MyLoginActivity.class);
                    startActivity(ii);
                } else if (val.equals("Exit")) {
                    stopService(new Intent(Swipetouch.this, MyService.class));
                    finish();
                }

            } catch (Exception e) {
                Toast.makeText(Swipetouch.this, e.toString(), Toast.LENGTH_SHORT).show();
            }
        }

    });
    // some other visual settings
    popupWindow.setFocusable(true);
    popupWindow.setWidth(250);
    // popupWindow.setHeight(300);
    popupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);

    // set the list view as pop up window content
    // SET WALLPAPER IMAGE
    /*
     * popupWindow.setBackgroundDrawable(getWallpaper()); popupWindow.setHeight(300);
     */
    // layout.setBackgroundResource(R.drawable.sshadow);
    // layout.setBackgroundColor(Color.TRANSPARENT);
    // popupWindow.setContentView(layout);

    popupWindow.setBackgroundDrawable(new ColorDrawable(
            Android.graphics.Color.TRANSPARENT));
    popupWindow.setContentView(listView);

    return popupWindow;
}
2
parik dhakan
  try {
                    Java.lang.reflect.Field[] fields = popup.getClass().getDeclaredFields();
                    for (Java.lang.reflect.Field field : fields) {
                        if ("mPopup".equals(field.getName())) {
                            field.setAccessible(true);
                            Object menuPopupHelper = field.get(popup);
                            Class<?> classPopupHelper = Class
                                    .forName(menuPopupHelper.getClass().getName());
                            Method setForceIcons = classPopupHelper
                                    .getMethod("setForceShowIcon", boolean.class);
                            setForceIcons.invoke(menuPopupHelper, true);
                            break;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
1
Bilel Bouali

Ce code fonctionne dans mon application.

Essaye ça :-

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
xmlns:tools="http://schemas.Android.com/tools"
tools:context=".LocationDetailsActivity">


<item xmlns:tools="http://schemas.Android.com/tools"
    Android:icon="@Android:drawable/ic_menu_mapmode"
    app:showAsAction="ifRoom"
    Android:title="@string/title_of_menu"
    tools:context=".LocationDetailsActivity">
    //the menu list with icon
    <menu>
        <item
            Android:id="@+id/action_map_type_normal"
            Android:orderInCategory="100"
            Android:icon="some_icon" //place your icon here
            Android:title="Vacation spots" />
        <item
            Android:id="@+id/action_map_type_satellite"
            Android:orderInCategory="100"
            Android:icon="some_icon" //place your icon here
            Android:title="Friends and family" />
        <item
            Android:id="@+id/action_map_type_hybrid"
            Android:orderInCategory="100"
            Android:icon="some_icon" //place your icon here
            Android:title="Restaurants" />
    </menu>
</item>

Vous pouvez suivre le tutoriel de ces différents fournisseurs 

http://developer.Android.com/guide/topics/ui/actionbar.html

http://www.vogella.com/tutorials/AndroidActionBar/article.html

http://www.androidhive.info/2013/11/Android-working-with-action-bar/

Tous ont d'excellents exemples et le code source pour vous aider

J'espère que cela vous aidera :)

1
Biswajit

Solution plus facile. Ajoutez ceci juste avant votre méthode .show ().

try {
  Field mFieldPopup=popupMenu.getClass().getDeclaredField("mPopup");
  mFieldPopup.setAccessible(true);
  MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popupMenu);
  mPopup.setForceShowIcon(true);
} catch (Exception e) {}
0
Tommie