繁体   English   中英

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

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

我想在Android中实现像Twitter这样的自定义弹出菜单,例如项目和图片,但我不知道用于此的组件是什么。

在Material Design网站上,谷歌提出了这个解决方案 所以我认为,有一个本机解决方案来实现这一目标。

在此输入图像描述

我尝试使用弹出菜单 ,但我找不到如何自定义此视图的布局。

您可以使用ListPopupWindow ,提交自定义适配器,通过它可以控制ListPopupWindow的每一行的ListPopupWindow 至于普通的PopupWindow你必须提供一个锚视图,另外你必须在ListPopupWindow的实例上调用setContentWidth ,它将弹出窗口的宽度设置为其内容的大小。 这是一个你必须付出的小代价,但对于一个小数据集来说并不是什么大问题。 我有这个实用工具方法来检索行的最大宽度:

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

有一个名为PopupMenu的小部件,它基本上是一个锚定到特定视图的菜单。 一个缺点是它默认不显示图标。

但是,您可以使用反射并调用setForceShowIcon来显示它们。 您需要的代码是:

  • 由于PopupMenu锚定到特定视图,因此ActionBar项具有actionLayout属性。 该布局( 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 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> 
  • 你的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> 
  • 最后,在单击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); } 

请注意,要在菜单中获取多行文本,您还需要对弹出菜单项使用actionLayout

使用弹出列表片段 关于片段的好处是你可以轻松地为它们制作动画 (如果你不理解片段,我建议先阅读Fragment Introduction

如果要完全控制弹出内容,请参阅Dialog Fragment

我有同样的问题。但最后我在自己的解决方案中发现我正在分享我的代码。 希望能帮到你。

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

此代码在我的应用程序中工作。

尝试这个 :-

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

您可以从这些不同的提供程序中查看教程

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/

所有这些都有很好的示例和源代码来帮助您

希望这对你有所帮助:)

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

更简单的解决方案 在.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