记录一下Popmenu的使用以及一些坑:自定义Popupmenu、Menu、Popupmenu添加icon

mac2024-03-24  28

今天就记录一下昨天写bug的时候使用Popupmenu的时候遇到的一些问题吧

尝试使用Popupmenu,避免不必要的坑。我贴的代码都是我最后的代码。记录自己看一下。后来参考的人就看看步骤就行。先看看我最后的效果图:

壹、Popupmenu的基本使用,定义和获取对应的menu菜单项。贰、Popupmenu设置字体风格和弹出定位。添加分割线。叁、为Popupmenu添加icon:两种方法:反射、子菜单模式a、利用反射强制展示icon。这里面有点坑。b、子菜单模式,不用反射,直接显示。 肆、动态管理Popupmenu表单项。隐藏菜单中指定的选项。伍、为Popupmenu菜单设置监听。

壹、Popupmenu的基本使用,定义和获取对应的menu菜单项。

首先我们来定义一个menu.xml来放我们的菜单项目。 menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/changeIO" android:orderInCategory="120" android:icon="@drawable/changeio" android:title="切换进出方向" /> <item android:id="@+id/workstart" android:orderInCategory="120" android:icon="@drawable/work" android:title="出工" /> <item android:id="@+id/workfinish" android:orderInCategory="120" android:icon="@drawable/finishwork" android:title="收工" /> <item android:id="@+id/rollcall" android:orderInCategory="120" android:icon="@drawable/rollcall" android:title="点名" /> <item android:id="@+id/areactrl" android:orderInCategory="120" android:icon="@drawable/areactrl" android:title="零星流动" /> </menu> 然后我们直接把菜单按钮设置监听,在里面定义popupmenu。获取表单信息即可。下面两行代码放进去就行。功能就是点击图标按钮即可弹出菜单。 private View.OnClickListener ioSwitcherListener = v -> { PopupMenu popupMenu = new PopupMenu(FaceActivity.this, v); //FaceActivity是当前使用类 popupMenu.getMenuInflater().inflate(R.menu.face_menu, popupMenu.getMenu()); popupMenu.show(); //关键,弹出菜单显示 } 我们来看看具体效果图吧。这是我之前啥效果都没加的时候。只列了两个选项。可以看到没有分割线。白白的很丑。我们后面爱继续优化吧。

贰、Popupmenu设置字体风格和弹出定位。添加分割线。

由于风格单调,我们需要把它弄得好看一点。做安卓的应该都做过按钮。和按钮这些一样。我们看可以单独为他定制一个style。在value文件夹里面新建itemstyle.xml <?xml version="1.0" encoding="utf-8"?> <resources> <style name="mainStyle" parent="Theme.AppCompat"> <!--主风格、mainStyle--> <item name="android:dropDownListViewStyle">@style/popmenuDivier</item> <item name="android:textAppearanceSmallPopupMenu">@style/popmenuText</item> <item name="android:textAppearanceLargePopupMenu">@style/popmenuText</item> </style> <!--popmenu的字体颜色--> <style name="popmenuText"> <item name="android:textColor">@color/white</item> <item name="android:textSize">20sp</item> <item name="android:gravity">center</item> </style> <!--popMenu分割线的颜色--> <style name="popmenuDivier"> <item name="android:divider">@color/md_blue_600</item> <item name="android:dividerHeight">2sp</item> </style> </resources> 关于这个style文件,我具体还没摸清哪些风格对应的是啥。主风格里面嵌套其他风格。引用继承的关系。主风格parent网上的都是写的AppThem。我用这个无法编译。我开始把它删了。所有都可以用。这个parent其实可有可无。但是后面添加icon就出问题了。所以我才加了Theme.AppCompat。但是加了这个就无法使用popupmenu的背景、定位的自定义风格。目前没找到问题所在。希望后来的大佬知道的指点一下。因为我的也可以将就着用。我就没添加背景和定位!关于定位和背景需要的。大家可以参考一下这篇博客最后在对应使用的activity配置,例如我的是FaceActivity,把这一条添加到对应的activity就行了。 我们来看看具体效果图,添加了分割线,字体风格和Theme.AppCompat默认背景风格。到这一步差不多就是下面的风格。奇怪的是没有定位它默认跑到一个合理的位置上了,免去了定位的烦恼。 由于之前我没有继承parent。定位和背景也可以正常使用看看你我的先后对比图。这是没有设置定位和背景 这是设置了背景和定位的。这些在主风格都没继承parent的。可以看到就整齐美观了许多。

叁、为Popupmenu添加icon:两种方法:反射、子菜单模式

a、利用反射强制展示icon。这里面有点坑。

虽然定位,背景都设置了,但是还是觉得很丑。这时候我就尝试着为每个表单添加icon。也就是本文开始的那种效果。我搜了许多,都是用的反射显示。我也用的反射实现的。我们只需要在刚才定义popupmenu的后面加一段代码即可实现。 //使用反射,强制显示菜单图标 try { Field field = popupMenu.getClass().getDeclaredField("mPopup"); field.setAccessible(true); MenuPopupHelper mHelper = (MenuPopupHelper) field.get(popupMenu); mHelper.setForceShowIcon(true); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); }finally { popupMenu.show(); } 说到这里我就有话要说了。由于之前项目比较老了。这个MenuPopupHelper死都不出来。android.support.v7.widget报找不到。检查发现我导的包和别人用的不一样。我又尝试添加了一下依赖。 结果解决了么,并没有!又报错了。编译失败,说我v4和v7冲突了。反正就是这个问题。最后检查发现在另一个build.gradle里面还有个v4.我把它注释了就好了。貌似v4和v7差不多。但是有重合的部分。网上说把冲突的jar删了即可。

b、子菜单模式,不用反射,直接显示。

利用表嵌套,当然具体还看需求而定。我还没尝试如何怎么调整显示为我想要的效果。但至少提供了一种思路。这是我在谷歌上找到的。百度上的都是利用那个反射强制显示的。这个就直接第一步的代码啥都不用加。 <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/main" android:orderInCategory="120" android:title="主菜单" > <menu> <item android:id="@+id/changeIO" android:orderInCategory="120" android:icon="@drawable/changeio" android:title="切换进出方向" /> <item android:id="@+id/workstart" android:orderInCategory="120" android:icon="@drawable/work" android:title="出工" /> <item android:id="@+id/workfinish" android:orderInCategory="120" android:icon="@drawable/finishwork" android:title="收工" /> <item android:id="@+id/rollcall" android:orderInCategory="120" android:icon="@drawable/rollcall" android:title="点名" /> <item android:id="@+id/open" android:orderInCategory="120" android:icon="@drawable/areactrl" android:title="零星流动" /> </menu> </item> </menu>

肆、动态管理Popupmenu表单项。隐藏菜单中指定的选项。

这个问题不知道是我没找到还是啥,各大网站没找到对应的解决方案。最后在谷歌找到的。一种是比较愚蠢的,添加所需的menu项.可以参照着我的menu.xml看。但是这个蠢就蠢在我费劲千辛万苦添上去的icon又不在了。变成了这个样子。 popupMenu.getMenu().add(Menu.NONE, R.id.rollcall, Menu.NONE, "点名详情"); popupMenu.getMenu().add(Menu.NONE, R.id.workfinish, Menu.NONE, "收工"); popupMenu.getMenu().add(Menu.NONE, R.id.changeIO, Menu.NONE, "切换进出方向");

另外就是比较nice的解决方案了。原理就是把他的显示参数设置为不可见。答案来自谷歌。手动笑哭!!我把其中两个隐藏了。这样我们就可以根据后端传过来的标识显示对应的menu项。最后效果:看着就会很nice !我特么把这生生搞成了进化史!哈哈 popupMenu.getMenu().findItem(R.id.rollcall).setVisible(false); popupMenu.getMenu().findItem(R.id.workfinish).setVisible(false);

伍、为Popupmenu菜单设置监听。

最难的我们都经历了,剩下来这个就比较简单了。直接Switch就行了。哇,写累了直接上代码吧!手动滑稽!直接加在popupmenu.show后面就行 popupMenu.setOnMenuItemClickListener( new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.rollcall: Comm.loger.output("切换点名。"); break; case R.id.workstart: Comm.loger.output("切换出工。"); break; //此处省略一万字 default: // 隐藏该对话框 Toast.makeText(FaceActivity.this, "您单击了【" + item.getTitle() + "】菜单项" , Toast.LENGTH_SHORT).show(); } return true; } });
写到这儿也差不多,好久没写这么长的博客了。刚下完班拖着疲惫的身体来写写日记吧。如果对你有用,就留个赞吧!哈哈。手动滑稽!有点乱,有误的话望指正!谢谢_最后的最后特别鸣谢以下博客提供的参考思路。 1、V4和V7冲突参考思路 2、自定义popupmenu参考 3、自定义popupmenu参考2 4、添加icon思路,现在访问个stackoverflow都卡的不行,还得翻个墙 5、隐藏对应menu项参考
最新回复(0)