Toolbar
由 AndroidX 库提供的用来替代 ActionBar 的一个控件。
详细信息ActionBar 即每个 Activity 最顶部的那个标题栏,任何新建的项目默认都会显示,但它被限定只能位于 Activity 的顶部,从而不能实现一些 Material Design 的效果,因此官方现在已经不再建议使用,可在 res/values/styles.xml 文件中设置为不带 ActionBar 的主题。更加推荐的是 Toolbar,它不仅继承了 ActionBar 的所有功能,而且灵活性很高,可配合其它控件完成一些 Material Design 的效果。
首先指定一个不带 ActionBar 的主题,常用的有两种:
- Theme.AppCompat.NoActionBar。表示深色主题,它会将界面的主体颜色设为深色,陪衬颜色设为浅色。
- Theme.AppCompat.Light.NoActionBar。表示浅色主体,它会将界面的主体颜色设为浅色,陪衬颜色设为深色。
在 XML 中添加控件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
// 指定了一个新的命名空间,这是由于许多 Material 属性是在新系统中新增的,为了兼容老系统。
// 在 MD 的开发中会经常用到它
// xmlns:app="http://schemas.android.com/apk/res-auto"
// ----------------------------------------------------------------------------
// Toolbar 控件由 appcompat 库提供
// 高度设置为 actionBar 的高度
// 让 Toolbar 单独使用深色主题。
//(系统主题为浅色,Toolbar 也会是浅色主题,其上的元素会自动使用深色系,从而和主体颜色区别开,这样字体是黑色会很丑。)
// 单独将弹出的菜单项指定为浅色主题。
//(现在 Toolbar 为深色主题,如果包含了菜单项,那么弹出的菜单项也会是深色主题,会很丑。)
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</LinearLayout>
修改标题栏上显示的文字内容:给 Activity 增加了 label 属性,如果不指定,默认使用 application 中指定的 label 内容。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.material">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ToolbarActivity"
android:label="Toolbar"/>
</application>
</manifest>
添加 action 按钮:res 目录 -> menu 文件夹 -> 新建文件(选择 Menu resource file )。
<?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 标签定义 action 按钮
// ------------------------------------------------------------------------
// app:showAsAction 指定按钮的显示位置:(为了兼容低版本系统,同样使用了 app 命名空间)
// always:表示永远显示在 Toolbar 中,如果屏幕空间不够则不显示。
// ifRoom:表示屏幕空间足够的情况下显示在 Toolbar 中,否则就显示在菜单当中。
// never:表示永远显示在菜单当中。
// ------------------------------------------------------------------------
// 注意:Toolbar 的 action 按钮只会显示图标。而菜单中的 action 按钮只会显示文字。
<item android:id="@+id/backup"
android:icon="@drawable/ic_backup"
android:title="Backup"
app:showAsAction="always" />
<item android:id="@+id/delete"
android:icon="@drawable/ic_delete"
android:title="Delete"
app:showAsAction="ifRoom" />
<item android:id="@+id/settings"
android:icon="@drawable/ic_settings"
android:title="Settings"
app:showAsAction="never" />
</menu>
修改代码:
class ToolbarActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_toolbar)
// 调用 setSupportActionBar 并将 Toolbar 的实例传入。
// 这样,既使用了 Toolbar,又让它的外观与功能都和 ActionBar 一致了。
setSupportActionBar(toolbar)
}
/**
* 在此方法中加载了 toolbar.xml 这个菜单文件
*/
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.toolbar, menu)
return true
}
/**
* 处理各个按钮的点击事件
*/
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.backup ->
Toast.makeText(this,"You clicked Backup",Toast.LENGTH_SHORT).show()
R.id.delete ->
Toast.makeText(this,"You clicked Delete",Toast.LENGTH_SHORT).show()
R.id.settings ->
Toast.makeText(this,"You clicked Settings",Toast.LENGTH_SHORT).show()
}
return true
}
}
滑动菜单
所谓的滑动菜单,就是将一些菜单选项隐藏起来,而不是放置在主屏幕上,然后可以通过滑动的方式将菜单显示出来。这种方式既节省了屏幕空间,又实现了非常好的动画效果。
DrawerLayout
它是一个布局,在布局中允许放入两个直接子控件。第一个子控件是主屏幕中显示的内容,第二个子控件是滑动菜单中显示的内容。
修改 XML 代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/drawerLayout">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/toolbar"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
</FrameLayout>
<!-- 滑动菜单中显示的内容,其实使用什么都可以,DrawerLayout 并没有限制只能使用固定的控件。 -->
<!-- 但是,android:layout_gravity 属性必须指定,因为要告诉 DrawerLayout 滑动菜单是在屏幕的左边还是右边。 -->
<!-- left:左边。 right:右边。 start:根据系统语言进行判断。 -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#FFF"
android:text="This is menu"
android:textSize="30sp" />
</androidx.drawerlayout.widget.DrawerLayout>
默认只能在屏幕边缘进行拖动时才能将菜单拖出来。现在,在 Toolbar 的最左边添加一个导航按钮,点击按钮也会将滑动菜单的内容展示出来。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
// 为滑动菜单添加导航按钮
// 调用 getSupportActionBar() 得到 ActionBar 的实例,虽然这个 ActionBar 的具体实现是由 Toolbar 实现的。
supportActionBar?.let {
// 当 ActionBar 不为空时,进行如下操作。
// 将导航按钮显示出来
it.setDisplayHomeAsUpEnabled(true)
// 设置导航按钮的图标。
// 实际上,Toolbar 最左侧的这个按钮就叫做 Home 按钮,
// 它默认的图标是一个返回的箭头,含义是返回上一个 Activity,这里将它默认的样式和功能都进行了修改。
it.setHomeAsUpIndicator(R.drawable.ic_menu)
}
}
...
/**
* 处理各个按钮的点击事件
*/
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
// 对 Home 按钮的点击事件进行处理,它的 id 永远是 android.R.id.home。
// 调用 DrawerLayout 的 openDrawer() 将滑动菜单展示出来,这里参数指定了和 XML 中的一致。
android.R.id.home -> drawerLayout.openDrawer(GravityCompat.START)
...
}
return true
}