In previous article we learned how to create custom overflow menu. In this article we will be going to learn about Popup Menu which is similar as Overflow Menu.
A PopupMenu displays a Menu in a modal popup window anchored to a View. The popup will appear below the anchor view if there is room, or above it if there is not. If the IME is visible the popup will not overlap it until it is touched. Touching outside of the popup will dismiss it.
1. Create a new project in Android Studio by navigating to File ⇒ New ⇒ New Project and fill required details. By default my activity is MainActivity.java.
2. Open strings.xml located under res=>values folder and add following strings.
1 2 3 4 5 6 7 8 9 |
<resources> <string name="app_name">Popup Menu Demo</string> <string name="contact_us">Contact Us</string> <string name="terms_and_conditions">Terms and Conditions</string> <string name="logout">Logout</string> <string name="default_popup_menu">Default Popup Menu</string> <string name="custom_popup_menu">Custom Popup Menu</string> <string name="custom_styled_menu">Styled Popup Menu</string> </resources> |
3. Create activity_main.xml and add the following code. Here there are three buttons which will open different types of popup menus.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" tools:context=".MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/main_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="16dp"> <Button android:id="@+id/show_default_popup_menu" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:onClick="showDefaultPopupMenu" android:text="@string/default_popup_menu" android:textColor="@android:color/white" android:textSize="15sp" /> <Button android:id="@+id/show_custom_popup_menu" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:background="@color/colorPrimary" android:onClick="showCustomPopupMenu" android:text="@string/custom_popup_menu" android:textColor="@android:color/white" android:textSize="15sp" /> <Button android:id="@+id/show_styled_popup_menu" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:background="@color/colorPrimary" android:onClick="showStyledPopupMenu" android:text="@string/custom_styled_menu" android:textColor="@android:color/white" android:textSize="15sp" /> </LinearLayout> </LinearLayout> |
4. Now let’s create menu for Popup naming popup_menu.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_contact_us" android:icon="@drawable/ic_contact_phone_black_24dp" android:title="@string/contact_us" /> <item android:id="@+id/action_terms_conditions" android:icon="@drawable/ic_assignment_black_24dp" android:title="@string/terms_and_conditions" /> <item android:id="@+id/action_logout" android:icon="@drawable/ic_power_settings_new_black_24dp" android:title="@string/logout" /> </menu> |
5. Now open your MainActivity.java and add the below code to it. As we will display the popup menu at the anchor of buttons only so we don’t need any other activity or xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
package com.popup.menu.demo; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.view.ContextThemeWrapper; import android.support.v7.widget.PopupMenu; import android.support.v7.widget.Toolbar; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import java.lang.reflect.Field; import java.lang.reflect.Method; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setUpToolbar(); } /** * set up toolbar */ private void setUpToolbar() { Toolbar toolbar = findViewById(R.id.main_toolbar); setSupportActionBar(toolbar); } /** * method to show default popup menu * * @param view */ public void showDefaultPopupMenu(View view) { showPopupMenu(view, false, R.style.MyPopupStyle); } /** * method to show custom popup menu with icons * * @param view */ public void showCustomPopupMenu(View view) { showPopupMenu(view, true, R.style.MyPopupStyle); } /** * method to show styled popup menu with icons * * @param view */ public void showStyledPopupMenu(View view) { showPopupMenu(view, false, R.style.MyPopupOtherStyle); } /** * method responsible to show popup menu * * @param anchor is a view where the popup will be shown * @param isWithIcons flag to check if icons to be shown or not * @param style styling for popup menu */ private void showPopupMenu(View anchor, boolean isWithIcons, int style) { //init the wrapper with style Context wrapper = new ContextThemeWrapper(this, style); //init the popup PopupMenu popup = new PopupMenu(wrapper, anchor); /* The below code in try catch is responsible to display icons*/ if (isWithIcons) { 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(); } } //inflate menu popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu()); //implement click events popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.action_contact_us: Toast.makeText(MainActivity.this, "Contact us clicked", Toast.LENGTH_SHORT).show(); break; case R.id.action_terms_conditions: Toast.makeText(MainActivity.this, "Terms and Conditions clicked", Toast.LENGTH_SHORT).show(); break; case R.id.action_logout: Toast.makeText(MainActivity.this, "Logout clicked", Toast.LENGTH_SHORT).show(); break; } return true; } }); popup.show(); } } |
Here in above MainActivity.java there are three types of Popup Menus as follows:
1 2 3 4 5 6 7 8 |
//init the popup PopupMenu popup = new PopupMenu(context, anchor); //inflate menu popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu()); //show menu popup.show(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//init the popup PopupMenu popup = new PopupMenu(context, anchor); /* The below code in try catch is responsible to display icons*/ 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(); } //inflate menu popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu()); //show menu popup.show(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//init the wrapper with style Context wrapper = new ContextThemeWrapper(this, R.style.MyPopupOtherStyle); //init the popup PopupMenu popup = new PopupMenu(wrapper, anchor); /* The below code in try catch is responsible to display icons*/ 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(); } //inflate menu popup.getMenuInflater().inflate(R.menu.popup_menu, popup.getMenu()); //show menu popup.show(); |
Here is the style code for Popup Menu:
1 2 3 4 5 6 7 8 9 |
<!-- Popup Other Style --> <style name="MyPopupOtherStyle" parent="Theme.AppCompat.Light.Dialog.Alert"> <!-- Used for the buttons --> <item name="colorAccent">@color/colorAccent</item> <!-- Used for the title and text --> <item name="android:textColorPrimary">@android:color/white</item> <!-- Used for the background --> <item name="android:background">@color/colorPrimary</item> </style> |
6. Full styles.xml code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <!-- Popup Style --> <style name="MyPopupStyle" parent="Theme.AppCompat.Light.Dialog.Alert"> <!-- Used for the buttons --> <item name="colorAccent">@color/colorAccent</item> <!-- Used for the title and text --> <item name="android:textColorPrimary">@android:color/black</item> <!-- Used for the background --> <item name="android:background">@android:color/white</item> </style> <!-- Popup Other Style --> <style name="MyPopupOtherStyle" parent="Theme.AppCompat.Light.Dialog.Alert"> <!-- Used for the buttons --> <item name="colorAccent">@color/colorAccent</item> <!-- Used for the title and text --> <item name="android:textColorPrimary">@android:color/white</item> <!-- Used for the background --> <item name="android:background">@color/colorPrimary</item> </style> </resources> |
7. Finally, all done run your code.
Thanks.
Subscribe to us and get the latest news.
5 Comments
mza
Tuesday, August 27th, 2019thanks,
Jakub Bober
Wednesday, May 26th, 2021How to hide navigation bar when PopupMenu is showing?
Dr. Droid
Thursday, May 27th, 2021Hi Jakub,
Try this link : https://stackoverflow.com/questions/21724420/how-to-hide-navigation-bar-permanently-in-android-activity
Thanks
Attaullah
Saturday, August 21st, 2021Great
Jongtak
Wednesday, October 26th, 2022How to change text color of popup menu when menu-item was selected/hovered?
I’ve searched a lot here and there, but I can’t find a way.
Thanks.