Menú desplegable / emergente personalizado de Android

127

¿Cómo hago un menú desplegable / emergente personalizado anclado a un botón?

Necesito que funcione como el menú emergente (anclado a una vista) y que haga algo cuando haga clic en un elemento del menú.

¿Cómo agrego elementos al menú por código, manteniendo la altura del menú y haciendo que se pueda desplazar si hay más de 5 elementos? No necesito agregar ninguna imagen, solo texto.

ingrese la descripción de la imagen aquí

stanete
fuente

Respuestas:

315

Actualización : para crear un menú emergente en Android con Kotlin, consulte mi respuesta aquí .

Para crear un menú emergente en Android con Java:

Cree un archivo de diseño activity_main.xmlen el res/layoutdirectorio que contenga solo un botón.

Nombre del archivo: activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    tools:context=".MainActivity" >  

    <Button  
        android:id="@+id/button1"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_alignParentLeft="true"  
        android:layout_alignParentTop="true"  
        android:layout_marginLeft="62dp"  
        android:layout_marginTop="50dp"  
        android:text="Show Popup" />  

</RelativeLayout>  

Crear un archivo popup_menu.xmlen el res/menudirectorio

Contiene tres elementos como se muestra a continuación.

Nombre del archivo: poupup_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" >  

    <item  
        android:id="@+id/one"  
        android:title="One"/>  

    <item  
        android:id="@+id/two"  
        android:title="Two"/>  

    <item  
        android:id="@+id/three"  
        android:title="Three"/>  

</menu>  

Clase MainActivity que muestra el menú emergente al hacer clic en el botón.

Nombre del archivo: MainActivity.java

public class MainActivity extends Activity {  
    private Button button1;  

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //Creating the instance of PopupMenu
                PopupMenu popup = new PopupMenu(MainActivity.this, button1);
                //Inflating the Popup using xml file
                popup.getMenuInflater()
                    .inflate(R.menu.popup_menu, popup.getMenu());

                //registering popup with OnMenuItemClickListener
                popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    public boolean onMenuItemClick(MenuItem item) {
                        Toast.makeText(
                            MainActivity.this,
                            "You Clicked : " + item.getTitle(),
                            Toast.LENGTH_SHORT
                        ).show();
                        return true;
                    }
                });

                popup.show(); //showing popup menu
            }
        }); //closing the setOnClickListener method
    }
}

Para agregar mediante programación:

PopupMenu menu = new PopupMenu(this, view);

menu.getMenu().add("One");
menu.getMenu().add("Two");
menu.getMenu().add("Three");

menu.show();

Siga este enlace para crear un menú mediante programación.

Shylendra Madda
fuente
¡¡Hey, gracias!! ¿Qué pasa si quiero agregar más elementos al menú? ¿Puedo hacer eso por código?
stanete
bienvenido .. sí, puedes agregar más elementos en popup_menu.xml
Shylendra Madda
3
Ok, descubrí cómo agregar elementos: menu.getMenu (). Add ("item"); Pero, ¿cómo puedo personalizar el menú?
stanete
1
Ahora también se puede usar en versiones inferiores, es decir, por debajo de 3.0 (nido de abeja) mediante el uso de la biblioteca de compatibilidad v7 compat ..
AndroidMech
1
<item android: id = "@ + id / google_plus" android: title = "@ string / menu_google_plus" android: icon = "@ drawable / add_by_gp" android: showAsAction = "ifRoom | withText" /> así es como agregué, pero no puedo ver la imagen con el texto
Mr.G
8

Sé que esta es una pregunta antigua, pero encontré otra respuesta que funcionó mejor para mí y no parece aparecer en ninguna de las respuestas.

Crea un diseño xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="5dip"
    android:paddingBottom="5dip"
    android:paddingStart="10dip"
    android:paddingEnd="10dip">

<ImageView
    android:id="@+id/shoe_select_icon"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:layout_gravity="center_vertical"
    android:scaleType="fitXY" />

<TextView
    android:id="@+id/shoe_select_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:textSize="20sp"
    android:paddingStart="10dp"
    android:paddingEnd="10dp"/>

</LinearLayout>

Cree una ListPopupWindow y un mapa con el contenido:

ListPopupWindow popupWindow;
List<HashMap<String, Object>> data = new ArrayList<>();
HashMap<String, Object> map = new HashMap<>();
    map.put(TITLE, getString(R.string.left));
    map.put(ICON, R.drawable.left);
    data.add(map);
    map = new HashMap<>();
    map.put(TITLE, getString(R.string.right));
    map.put(ICON, R.drawable.right);
    data.add(map);

Luego, al hacer clic, muestre el menú con esta función:

private void showListMenu(final View anchor) {
    popupWindow = new ListPopupWindow(this);

    ListAdapter adapter = new SimpleAdapter(
            this,
            data,
            R.layout.shoe_select,
            new String[] {TITLE, ICON}, // These are just the keys that the data uses (constant strings)
            new int[] {R.id.shoe_select_text, R.id.shoe_select_icon}); // The view ids to map the data to

    popupWindow.setAnchorView(anchor);
    popupWindow.setAdapter(adapter);
    popupWindow.setWidth(400);
    popupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            switch (position){
                case 0:
                    devicesAdapter.setSelectedLeftPosition(devicesList.getChildAdapterPosition(anchor));
                    break;
                case 1:
                    devicesAdapter.setSelectedRightPosition(devicesList.getChildAdapterPosition(anchor));
                    break;
                default:
                    break;
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    devicesAdapter.notifyDataSetChanged();
                }
            });
            popupWindow.dismiss();
        }
    });
    popupWindow.show();
}
Sir Codesalot
fuente
6

El camino de Kotlin

fun showPopupMenu(view: View) {
    PopupMenu(view.context, view).apply {
                menuInflater.inflate(R.menu.popup_men, menu)
                setOnMenuItemClickListener { item ->
                    Toast.makeText(view.context, "You Clicked : " + item.title, Toast.LENGTH_SHORT).show()
                    true
                }
            }.show()
}

ACTUALIZACIÓN: en el código anterior, la función de aplicación devuelve lo thisque no es necesario, por lo que podemos usar runlo que no devuelve nada y, para hacerlo aún más simple, también podemos eliminar las llaves del método showPopupMenu.

Aún más simple:

fun showPopupMenu(view: View) = PopupMenu(view.context, view).run {
            menuInflater.inflate(R.menu.popup_men, menu)
            setOnMenuItemClickListener { item ->
                Toast.makeText(view.context, "You Clicked : ${item.title}", Toast.LENGTH_SHORT).show()
                true
            }
            show()
        }
Sai
fuente
3

Primero, cree una carpeta llamada "menú" en la carpeta "res".

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="Search"/>
    <item
        android:id="@+id/add"
        android:icon="@android:drawable/ic_menu_add"
        android:title="Add"/>
    <item
        android:id="@+id/edit"
        android:icon="@android:drawable/ic_menu_edit"
        android:title="Edit">
        <menu>
            <item
                android:id="@+id/share"
                android:icon="@android:drawable/ic_menu_share"
                android:title="Share"/>
        </menu>
    </item>

</menu>

Luego, crea tu clase de actividad:

public class PopupMenu1 extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popup_menu_1);
    }

    public void onPopupButtonClick(View button) {
        PopupMenu popup = new PopupMenu(this, button);
        popup.getMenuInflater().inflate(R.menu.popup, popup.getMenu());

        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
                Toast.makeText(PopupMenu1.this,
                        "Clicked popup menu item " + item.getTitle(),
                        Toast.LENGTH_SHORT).show();
                return true;
            }
        });

        popup.show();
    }
}
sudhakara ks
fuente