How to realize this custom popup menu with Materia

2019-02-04 07:31发布

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.

7条回答
等我变得足够好
2楼-- · 2019-02-04 07:46
  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();
                }
查看更多
一纸荒年 Trace。
3楼-- · 2019-02-04 07:48

I have same issue.but finally i found at my own solution that i am sharing you my code. Hope that will help you.

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;
}
查看更多
beautiful°
4楼-- · 2019-02-04 07:51

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.

查看更多
Animai°情兽
5楼-- · 2019-02-04 08:00

This code is working in my app.

Try this :-

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

You can go through the tutorial from these different providers

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/

All of them have great examples and source code to help you out

Hope this help you :)

查看更多
够拽才男人
6楼-- · 2019-02-04 08:05

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;
}
查看更多
女痞
7楼-- · 2019-02-04 08:09

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

查看更多
登录 后发表回答