最近在研究关于MaterialDesign系类的内容,在研究Toolbar和NavigationView的时候,都使用到menu的内容。感觉自己不是很理解,可以说就是不知道,只会简单的写一个menu其他的什么都不会了。所以总结一下,希望对大家有帮助!!!
本文会讲解的知识点
- menu的使用
- menu的属性说明
- menu的使用注意事项
1. menu的使用
首先说明一下menu的存放位置,在创建项目的时候,是没有menu文件夹的,所以这里你要自己创建一个menu文件夹,然后新建一个menu文件。具体位置看下面这张图就可以了(因为这张图设置了相应的样式,所以弹出来的popup有一个背景色)!
下面我们来介绍关于menu文件怎么写,以及各个属性的含义
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_search"
android:icon="@drawable/ic_search_black_24dp"
android:title="搜索"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_cycling"
android:icon="@mipmap/ic_directions_bike_white_24dp"
android:title="去知乎的Toolbar"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_other"
android:title="去网易云音乐的ToolBar"
app:showAsAction="never" />
<item
android:id="@+id/menu_more"
android:title="更多">
<menu>
<item
android:id="@+id/menu_more1"
android:title="更多1" />
<item
android:id="@+id/menu_more2"
android:title="更多2" />
<item
android:id="@+id/menu_more3"
android:title="更多3" />
</menu>
</item>
</menu>
这是一个比较复杂的menu文件了,对于一般的menu不会有下面更多的那个item。还是先看一下效果吧!
看了效果之后,我们就很好理解其中的属性了,这里先解释一下相应的menu标签的属性值:
2. menu的属性说明
2.1 item的属性说明
这里面的属性很多,但是个人觉得有很多用不上,列出来的都是一些常用的属性。
- android:id 控件的ID
- android:icon 空间的图标(这里如果显示在Toolbar上面,会显示图片,在溢出菜单里面的话会只显示文字)
- android:title 显示的标题(也就是条目的内容)
- app:actionViewClass 引入一个View(这个是在实现搜索的时候用到的)
- app:showAsAction 显示方式
- ifRoom 如果有空间的话,会显示在ToolBar上,当空间不足的时候会显示在列表中
- always 一直显示在ToolBar上(如果没有空间的话,还是会显示在列表中,按先后顺序排列的)
- collapseActionView (一般要配合ifRoom一起使用)声明这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开。这个属性主要是实现自意义溢出菜单的。可以在它的里面设置一些item从而实现溢出菜单(这个自定义的溢出菜单和默认的溢出菜单唯一的区别就是它可以显示图标)
- never 不会显示在Toolbar上面,会显示在列列表中
- withText 表示显示的时候如果空间足够,会显示menu的title。但是我试了试没看到,还请知道的大神告知一声!
- android:titleCondensed 当你设置的内容过长的时候,可以使用这个属性进行简短的说明
- android:onClick 和View的onClick方法类似,设置一个点击事件
- android:checkable 菜单是否可以复选,如果可以复选的话设置成true
- android:checked 菜单是否可以被选中,如果可以被选中的话设置成true
- android:visible 菜单是否显示
- android:enabled 菜单项目是否可用,如果可用为true。主要是用在自定义溢出菜单的时候,是否可以进行相应的相应。
- android:orderInCategory 菜单的优先级,整数类型,数字越小越靠前
2.2 group的属性说明
主要是一个组的属性,和RadioGroup的样式类似,主要是实现复选的!里面的一些属性和上面是类似的,这里主要说明一个属性
- android:checkableBeharior 设置复选行为的类型
- none 没有可复选性
- all 组内的所有的项目都可以被复选(使用复选框)
- single 仅有一个项目能够被复选(使用单选按钮)
下面是关于group标签的使用
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/app_bar_search"
android:icon="@drawable/ic_search_black_24dp"
android:title="Search"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="always" />
<item
android:id="@+id/menu_delete"
android:icon="@mipmap/ic_delete"
android:title="删除"
app:showAsAction="always|collapseActionView">
<menu>
<group android:checkableBehavior="all">
<item android:title="group1" />
<item android:title="group2" />
<item android:title="group3" />
</group>
</menu>
</item>
<item
android:id="@+id/menu_setting"
android:icon="@mipmap/ic_delete"
android:title="设置"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_other"
android:icon="@mipmap/ic_delete"
android:title="不知道什么"
app:showAsAction="ifRoom" />
</menu>
这里就是通过自定义溢出菜单展示的group,具体效果看下面这张图
设置menu二级菜单的时候(无论是自定义还是系统的),前一级标签的文字颜色是黑色的,这个目前还没有找到好的解决方案,希望知道的给留个言!!!谢谢
3. menu的使用注意事项
这里我主要像说明一下我在开发中遇到的关于menu的一些问题
- Fragment中怎么显示menu?
- Activity和Fragment同时使用menu会怎样显示?
- Activity和Fragment同时处理点击事件怎么相应?
- menu的怎么动态改变?
- 多个Activity同时使用一个menu怎么简化操作?
这些问题,在平时的开发中,相信很多人都不会注意到!所以这里有必要和大家分享一下相关的内容。
3.1 Fragment中怎么显示menu?
Fragment中显示menu文件和Activity中是类似的,但是必须在挂在View之前添加
setHasOptionsMenu(true);
这句代码(基本上都是加载onCreat()上面),否则显示不出来的。。。
public class Main1Fragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main1, container, false);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main_fragment1, menu);
}
}
上面这段代码就是Fragment中显示menu的方法!
3.2 Activity和Fragment同时使用menu会怎样显示?
是不是觉得很奇怪的问题,你的答案是什么?是不是变得模棱两可了,其实有的面试官很关注这些细节。答案就是叠加显示,怎么个叠加显示呢?一个简单的说明,你在Activity中添加了一个设置的menu条目,如果你在Fragment中也写了一个,那么menu上会新增一个Fragment的menu文件。
3.3 Activity和Fragment同时处理点击事件怎么相应?
有的人可能会问了,那点击事件怎么处理呢?其实处理起来很简单,就是在
onOptionsItemSelected
处理相应的点击事件。但是有一个点需要注意,就是Activity的onOptionsItemSelected
方法的返回值!默认的情况下应该返回super.onOptionsItemSelected(item)
这个,防止处理了事件之后,Fragment收不到相应的点击事件!
- Activity的
onOptionsItemSelected
方法:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_setting:
Log.e(TAG, "onOptionsItemSelected: setting");
return true;
case R.id.menu_other:
Log.e(TAG, "onOptionsItemSelected: other" );
return true;
default:
return super.onOptionsItemSelected(item);
}
}
- Fragment的
onOptionsItemSelected
方法:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.fragment1:
Log.e(TAG, "onOptionsItemSelected: fragment1" );
return true;
case R.id.fragment2:
Log.e(TAG, "onOptionsItemSelected: fragment2" );
return true;
default:
return super.onOptionsItemSelected(item);
}
}
这样所有的点击事件就能得到相应的响应了。
3.4 menu的怎么动态改变?
有的人可能说动态的刷新了menu但是却没有成功,其实是没有调用
invalidateOptionsMenu();
通知menu刷新的方法造成的。下面我们来看看menu刷新的代码:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.fragment1:
Log.e(TAG, "onOptionsItemSelected: fragment1");
isRefeesh = true;
getActivity().invalidateOptionsMenu();
return true;
case R.id.fragment2:
Log.e(TAG, "onOptionsItemSelected: fragment2");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.fragment1);
if (isRefeesh) {
item.setTitle("刷新后的fragment1");
} else {
item.setTitle(item.getTitle());
}
}
这里说一下相应的逻辑,当调用invalidateOptionsMenu();
的时候会重走onPrepareOptionsMenu
这个方法,这里我用了一个标识去标记是否刷新,为什么会有这个标识呢?因为onPrepareOptionsMenu
准备menu的时候调用,所以刚一进来的时候就会被调用一次,点击后还会调用一次。
3.5 多个Activity同时使用一个menu怎么简化操作?
这个相当于继承的关系。其实这个问题也是相应的叠加问题,只要你记住menu是可以叠加的就可以。只要在你的
onCreateOptionsMenu
方法中加载父类的menu就可以了,像下面面这样!
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);//调用这一句保证父类的菜单项可以正常加载
getMenuInflater().inflate(R.menu.menu_main_fragment,menu);//加载子类自己的菜单项
return true;
}
基本上关于menu的使用就这些了,总结的可能还会有不到位的地方,如果你还有关于menu的使用问题,可以给我留言。