Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to realize this custom popup menu with Material Design Android?

I want to realize a custom popup menu like Twitter in Android for example with item and picture but I don't know what's the component used for that.

In Material Design website, google present this solution. So I think, there is a native solution to achieve this.

enter image description here

I tried with Popup menu, but I can't find how to customize the layout of this view like that.

like image 573
lopez.mikhael Avatar asked May 12 '15 07:05

lopez.mikhael


People also ask

How do I use pop up menu on Android?

Go to app > res > menu > right-click > New > Menu Resource File and create a menu resource file and name it as popup_menu. In the popup_menu file, we will add menu items. Below is the code snippet for the popup_menu. xml file.

What display a pop up 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.

What are the two types of popup menu?

There are three types of menus in Android: Popup, Contextual and Options. Each one has a specific use case and code that goes along with it.

What is popup menu in Android user interface?

Android Popup Menu displays a list of items in a vertical list which presents the view that invoked the menu and is useful to provide an overflow of actions related to specific content.


3 Answers

you can use a ListPopupWindow, submitting your custom adapter, through which you can control the layout of every single row of the ListPopupWindow. As for a normal PopupWindow you have to provide an anchor view and additionally you have to call setContentWidth on the instance of ListPopupWindow, which sets the width of the popup window by the size of its content. It is a small price you have to pay, but for a small dataset is not a big deal. I have this utility method to retrieve the max width of the row:

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; } 
like image 66
Blackbelt Avatar answered Sep 20 '22 16:09

Blackbelt


There's a widget called PopupMenu which is basically a menu anchored to a specific view. One drawback is that it doesn't display icons by default.

However, you can use reflection and call setForceShowIcon to reveal them. The code that you need is:

  • Since a PopupMenu is anchored to a specific view, your ActionBar item has an actionLayout attribute. That layout (action_item.xml) can be as simple as:

    <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 menu style that contains your item with the above layout

    <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>
    
  • Your popup_menu.xml, the layout you'll inflate for your 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>
    
  • And finally code to perform the inflation when an ActionBar item is clicked

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

Note, that to get that multi-line text in a menu, you'd need to use an actionLayout for your popup menu items too.

like image 31
Simas Avatar answered Sep 19 '22 16:09

Simas


Use a Pop-Up list fragment. The nice thing about fragments is that you can easily animate them (If you don't understand fragments I recommend first reading Fragment Introduction)

If you want complete control over the pop-up content then see Dialog Fragment

like image 30
Steven Mark Ford Avatar answered Sep 18 '22 16:09

Steven Mark Ford