工具栏不同于操作栏,这个在国内可能同行们会混淆。使用AppCompat库能够让老项目也能运行工具栏——这个Lollipop版本开始出现的组件。(其实,AppCompat库中也引入了能兼容不同版本的操作栏)
下面我们使用这个库中的内容新建菜单,使用的前提是你在项目中已经引入了这个库同时主题和activity都使用了库中定义的内容。
使用步骤:
1、使用前,需要创建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/new_crime"
android:icon="@drawable/ic_menu_add"
android:title="@string/new_crime"
app:showAsAction="ifRoom|withText"/>
</menu>
//当然如果你喜欢,你可以添加很多item
注意这里引入了app命名空间,showAsAction建议使用app命名空间下的——属于AppCompat库。
android:icon
属性能够使用系统内置的图片资源,如果使用就写入@android:drawable/ic_menu_add
,系统资源位于sdk/platform/android-2x/data/res目录下,如果使用系统内置资源,可能面临不同用户之间设备和系统版本导致的显示差异。解决此问题有三种方案:
- 使用定制图标,参考https://material.io/design/iconography/
- 将系统资源复制到项目drawable目录下
- 使用Android Asset Studio工具定制图标资源
2、创建回调函数
activity中有自己的菜单回调函数onCreateOptionMenu()
其实fragment也有一套回调函数,由FragmentManger调用,当activity收到操作系统的onCreateOptionMenu()方法回调请求时候,FragmentManager会调用其管理的fragment的onCreateOptionMenu()方法,使得这一过程得以实现,需要在fragment的oncreate方法中声明setHasOptionsMenu(true);
3、响应点击事件
重写onOptionItemSelected方法
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.new_crime:
Crime crime = new Crime();
CrimeLab.getInstance().addCrime(crime);
Intent intent = new Intent(getActivity(), CrimepagerActivity.class);
intent.putExtra(EXTRA_CRIME_ID, crime.getId());
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
4、实现层级式导航
android:parentActivityName=".CrimeListActivity
在点击工具栏的返回按钮时,会寻找目标activity,如果目标实例存在,则将目前栈中的其他activity出栈。该方法会让目标activity完全重建,这里要留意数据状态恢复。
有如下方案:
如果离目标activity只有一层activity,覆盖getParentActivityIntent()方法,finish当前界面直接回到目标界面。否则要添加带有extra信息的intent给目标activity。
5、更新子标题
核心方法是getActivity().getSupportActionBar().setSubtitle(subtitle)
如果要同时更新菜单,就调用getActivity().invalidateOptionsMenu();
该方法会回调菜单的onCreateOptionsMenu
方法
6、其他注意事项
防止设备旋转而让实例状态正确保存
在fragment中重写onSavedinstanceState方法。