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



在这里插入图片描述

壹、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;
                }
            });


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM