简体   繁体   English

如何使用Material Design Android实现此自定义弹出菜单?

[英]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. 我想在Android中实现像Twitter这样的自定义弹出菜单,例如项目和图片,但我不知道用于此的组件是什么。

In Material Design website, google present this solution . 在Material Design网站上,谷歌提出了这个解决方案 So I think, there is a native solution to achieve this. 所以我认为,有一个本机解决方案来实现这一目标。

在此输入图像描述

I tried with Popup menu , but I can't find how to customize the layout of this view like that. 我尝试使用弹出菜单 ,但我找不到如何自定义此视图的布局。

you can use a ListPopupWindow , submitting your custom adapter, through which you can control the layout of every single row of the ListPopupWindow . 您可以使用ListPopupWindow ,提交自定义适配器,通过它可以控制ListPopupWindow的每一行的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. 至于普通的PopupWindow你必须提供一个锚视图,另外你必须在ListPopupWindow的实例上调用setContentWidth ,它将弹出窗口的宽度设置为其内容的大小。 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;
}

There's a widget called PopupMenu which is basically a menu anchored to a specific view. 有一个名为PopupMenu的小部件,它基本上是一个锚定到特定视图的菜单。 One drawback is that it doesn't display icons by default. 一个缺点是它默认不显示图标。

However, you can use reflection and call setForceShowIcon to reveal them. 但是,您可以使用反射并调用setForceShowIcon来显示它们。 The code that you need is: 您需要的代码是:

  • Since a PopupMenu is anchored to a specific view, your ActionBar item has an actionLayout attribute. 由于PopupMenu锚定到特定视图,因此ActionBar项具有actionLayout属性。 That layout ( action_item.xml ) can be as simple as: 该布局( action_item.xml )可以简单如下:

     <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 ActionBar菜单样式,包含具有上述布局的项目

     <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 你的popup_menu.xml ,你将为你的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 最后,在单击ActionBar项目时执行通胀的代码

     @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. 请注意,要在菜单中获取多行文本,您还需要对弹出菜单项使用actionLayout

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 ) 关于片段的好处是你可以轻松地为它们制作动画 (如果你不理解片段,我建议先阅读Fragment Introduction

If you want complete control over the pop-up content then see Dialog Fragment 如果要完全控制弹出内容,请参阅Dialog Fragment

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

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://developer.android.com/guide/topics/ui/actionbar.html

http://www.vogella.com/tutorials/AndroidActionBar/article.html http://www.vogella.com/tutorials/AndroidActionBar/article.html

http://www.androidhive.info/2013/11/android-working-with-action-bar/ 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 :) 希望这对你有所帮助:)

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

Easier solution. 更简单的解决方案 Add this just before you .show() method. 在.show()方法之前添加它。

try {
  Field mFieldPopup=popupMenu.getClass().getDeclaredField("mPopup");
  mFieldPopup.setAccessible(true);
  MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popupMenu);
  mPopup.setForceShowIcon(true);
} catch (Exception e) {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM