Android custom dropdown/popup menu

219,809

Solution 1

Update: To create a popup menu in android with Kotlin refer my answer here.

To create a popup menu in android with Java:

Create a layout file activity_main.xml under res/layout directory which contains only one button.

Filename: 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>  

Create a file popup_menu.xml under res/menu directory

It contains three items as shown below.

Filename: 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>  

MainActivity class which displays the popup menu on button click.

Filename: 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
    }
}

To add programmatically:

PopupMenu menu = new PopupMenu(this, view);

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

menu.show();

Follow this link for creating menu programmatically.

Solution 2

I know this is an old question, but I've found another answer that worked better for me and it doesn't seem to appear in any of the answers.

Create a layout 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>

Create a ListPopupWindow and a map with the content:

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

Then on click, display the menu using this function:

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

Solution 3

The Kotlin Way

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

UPDATE: In the above code, the apply function returns this which is not required, so we can use run which don't return anything and to make it even simpler we can also remove the curly braces of showPopupMenu method.

Even Simpler:

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

Solution 4

First, create a folder named “menu” in the “res” folder.

<?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>

Then, create your Activity Class:

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();
    }
}
Share:
219,809
stanete
Author by

stanete

android developer &amp; machine intelligence enthusiast

Updated on April 17, 2020

Comments

  • stanete
    stanete about 4 years

    How do I do a custom dropdown/popup menu anchored to a button?

    I need it to work like the popup menu (anchored to a view), and do something when I click an item from the menu.

    How do I add items to the menu by code, keeping menu's height and make it scrollable if there are more than 5 items. I don't need to add any images, just text.

    enter image description here

  • stanete
    stanete over 10 years
    Hey thank you!! What if I want to add more items to the menu?. Can I do that by code?
  • Shailendra Madda
    Shailendra Madda over 10 years
    welcome.. yes you can add more items in popup_menu.xml
  • stanete
    stanete over 10 years
    But how can I do it in my main class? How can I add items via java?
  • stanete
    stanete over 10 years
    Ok I found out how to add items: menu.getMenu().add("item"); But how can I customize the menu?
  • Shailendra Madda
    Shailendra Madda over 10 years
    you can customize it like by using popup.getMenu().add(groupId, itemId, order, title);
  • stanete
    stanete over 10 years
    I mean the width, the background, etc.
  • Shailendra Madda
    Shailendra Madda over 10 years
    Once refer this it may helps you stackoverflow.com/questions/4591164/…
  • Bahadır Yıldırım
    Bahadır Yıldırım over 10 years
    @DavidStanete If this provides a solution to your question, don't forget to mark this answer as accepted. If you have any follow-up questions, feel free to ask a new question and provide a link.
  • AndroidMech
    AndroidMech almost 10 years
    Now it can also be used in lower versions ie below 3.0(honeycomb) by using the v7 compat support library..
  • Shailendra Madda
    Shailendra Madda almost 10 years
    @Mr.G Yes, You can add icon too by adding this line in popup_menu.xml android:icon="@drawable/ic_action_camera" in every menu item
  • Mr.G
    Mr.G almost 10 years
    <item android:id="@+id/google_plus" android:title="@string/menu_google_plus" android:icon="@drawable/add_by_gp" android:showAsAction="ifRoom|withText" /> this is how i added , but i cant see image with text
  • Shailendra Madda
    Shailendra Madda almost 10 years
    Replace this android:showAsAction="ifRoom|withText" with app:showAsAction="always|withText"
  • Mr.G
    Mr.G almost 10 years
    i replaced with app:showAsAction="always|withText" , but it gives me an error, i put android:showAsAction="always|withText", but it didnt give me an image
  • Shailendra Madda
    Shailendra Madda almost 10 years
    is there an image add_by_gp in drawable folder??
  • Mr.G
    Mr.G almost 10 years
  • Ankur1994a
    Ankur1994a over 8 years
    @ShylendraMadda Heyy thanks, this is really needfull.
  • Shailendra Madda
    Shailendra Madda over 7 years
    Glad to helped you.. @anuragshrivastava
  • Shailendra Madda
    Shailendra Madda over 7 years
    @FloWe for that you might look this stackoverflow.com/questions/27782846/…
  • Flo We
    Flo We over 7 years
    @ShylendraMadda thanks, but i meant setting a custom adapter for the Popup to display items instead of XML Menues.
  • Shailendra Madda
    Shailendra Madda over 5 years
    @FloWe It should be a new question