首页 > 技术文章 > 《Android 编程权威指南》学习笔记 : 第14章 应用栏

easy5weikai 2022-06-01 14:31 原文

第14章 应用栏

应用栏菜单

在 Xml 文件中定义菜单

  • 先定义 String 字符串资源,作为菜单项的名称
    代码清单:res/values/strings.xml
<resources>
    ...
    <string name="new_crime">New Crime</string>
</resources>
  • 添加菜单xml文件
    右键res目录,选择【New -> Android resource file】,
    菜单定义文件要遵循与布局文件一样的命名原则

点击【OK】后,自动生成菜单xml文件,

代码清单:res/menu/fragment_crime_list

<menu xmlns:android="http://schemas.android.com/apk/res/android"

</menu>

为菜单定义文件添加菜单项:

<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="@android:drawable/ic_menu_add"
        android:title="@string/new_crime"
        app:showAsAction="ifRoom|withText"/>
</menu>
  • @+id/new_crime 是菜单的Id,后面需要Id来确认点击的是哪个菜单项

创建 Fragment 菜单

class CrimeListFragment : Fragment() {

   ...
   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.fragment_crime_list, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.new_crime -> {
                var crime = Crime()
                crimeListViewModel.addCrime(crime)
                callbacks?.onCrimeSelected(crime.id)
                true
            }else -> return super.onOptionsItemSelected(item)

        }
    }
}
  • setHasOptionsMenu(true): Activity中的菜单的onCreateOptionsMenu()方法是有Android操作系统回调,
    而 Fragment的菜单的onCreateOptionsMenu()方法是由FragmentManager回调,故需要以下代码让FragmentManager知道需要调用
    Fragment的菜单的onCreateOptionsMenu()的方法
setHasOptionsMenu(true)
  • onCreateOptionsMenu : 使用菜单文件填充菜单
  • onOptionsItemSelected:响应选择菜单选项事件
    • 默认返回 父类的 return super.onOptionsItemSelected(item)

使用 Android Asset Studio

为 Action Bar 的菜单添加自定义图标
右键点击 res/drawable 目录,选择 New -> ImageAsset 菜单项,弹出Asset Studio

Ion Type:选择 Action Bar and Tab Icons
Name: ic_menu_add

选择一个 add 的图标

点击【OK】,【Next】按钮,

Asset Studio 会生成hdpi、xxhdpi等类型的图标

点击 Finsh按钮,生成的图标资源

修改菜单的布局文件,引用新的图标
代码清单:res/menu/fragment_crime_list.xml

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

新的菜单项图标效果:

图标是黑色的,把刚才的图标删除,重复上述步骤,在下面这一步,选择黑色主题,这样图标的颜色就是白色,在黑色主题上就能看得见白色图标了

重启编译,运行设备

应用栏、ActionBar(操作栏)、Tool Bar(工具栏)

Android 5.0(API 21) 开始,应用栏都是优先使用新引入的 ToolBar 类来实现的

ActionBar(操作栏)的限制很多:整个应用程序只能配置一个操作栏,并且位置和尺寸必须固定(位于屏幕顶部)
ToolBar(工具栏)就没有这个限制:每个activity 、Fragment 都可以有自己独立的应用栏,位置任意

AppCompat版应用栏

AppCompat版应用栏使用 Jetpack版的Toobar来实现。
要使用 AppCompat版应用栏,引入 AppCompatActivity的 supportFragmentManager的属性:

        val appCompatActivity = this as AppCompatActivity
        val appBar = appCompatActivity.supportActionBar as Toolbar

但是就目前创建默认项目来看,查看主题文件
/res/values/themes/themes.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.CriminalIntent" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
       <item>....
    </style>
</resources>

从主题:Theme.MaterialComponents.DayNight.DarkActionBar 来看,用的是 ActionBar,如果直接在代码中强行转换为 Toolbar 是会抛出异常的。
要应用 ToolBar 还是得查阅下资料。

引用到AppCompat版应用栏,就可以做一些应用栏设置,比如:设置标题:

  appBar.setTitle(R.string.crime_list_title)

推荐阅读