什么是 Toolbar
A Toolbar is a generalization of action bars for use within application layouts. While an action bar is traditionally part of an Activity's opaque window decor controlled by the framework, a Toolbar may be placed at any arbitrary level of nesting within a view hierarchy. An application may choose to designate a Toolbar as the action bar for an Activity using the setSupportActionBar() method.
以上是官方的介绍,简单来说 Toolbar 是在 Android 5.0 开始推出的一个 Material Design 风格的导航控件,Toolbar 可作为应用的导航控件,可以替代以前的 ActionBar。比 ActionBar 更佳灵活,不一定要固定在 Activity 的顶部,而是可以嵌套在任意位置。应用可以使用setSupportActionBar()
方法将 Toolbar 设置为 Activity 的 ActionBar。
Toolbar 为我们提供了一些可定制的修改属性,根据API文档的介绍,主要有以下几类:
- 可设置导航栏图标
- 可设置 App 的 logo
- 可设置标题和子标题
- 可添加一个或多个的自定义控件
- 可添加 ActionMenu
简单使用
按照惯例,我们先看一下效果图:
从效果图来看,从左到右分别是我们设置的 导航栏图标、App的logo、标题和副标题、自定义控件、ActionMenu。下面我们来看具体的代码实现。
- 引入v7包
由于 Toolbar 是v7包的一个控件,首先需要引入该包
implementation 'com.android.support:appcompat-v7:26.1.0'
- XML 添加 Toolbar
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary">
<!--此处可以添加自定义控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="custom"
android:textColor="@android:color/white"
android:textSize="16sp"/>
</android.support.v7.widget.Toolbar>
- 创建 menu_toolbar.xml 存放在 res/layout/menu 目录下,用于为 Toolbar 设置 ActionMenu
<?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/action_search"
android:icon="@drawable/ic_search_white_24dp"
android:title="搜索"
app:showAsAction="ifRoom"/>
<!--右侧设置条目,收起-->
<item
android:id="@+id/action_setting"
android:title="设置"
app:showAsAction="never"/>
<item
android:id="@+id/action_help"
android:title="帮助"
app:showAsAction="never"/>
</menu>
重点关注一下 app:showAsAction
属性,该属性有以下几种取值
- always:使菜单项一直显示在 Toolbar 上
- ifRoom:如果有足够的空间,这个值会使菜单项显示在 Toolbar 上
- never:使菜单项永远都不出现在 Toolbar 上,在…的子项中显示
- withText:使菜单项和它的图标,菜单文本一起显示
- Activity 中获取并设置相关属性值,以及事件监听
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 隐藏系统默认的导航栏
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_toolbar);
ButterKnife.bind(this);
initToolbar();
}
private void initToolbar() {
// 设置ActionMenu布局(方式一)
mToolbar.inflateMenu(R.menu.menu_toobar);
// 设置logo
mToolbar.setLogo(R.mipmap.ic_launcher_round);
// 设置标题
mToolbar.setTitle("title");
// 设置副标题
mToolbar.setSubtitle("sub title");
// 设置标题的字体颜色
mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
// 设置子标题的字体颜色
mToolbar.setSubtitleTextColor(getResources().getColor(android.R.color.white));
// setSupportActionBar(mToolbar);
// 设置导航按钮图标
mToolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp);
// 设置更多按钮图标
mToolbar.setOverflowIcon(getResources().getDrawable(R.drawable.ic_more_horiz_white_24dp));
// 设置导航图标的点击事件(方式一)
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDrawerLayout.openDrawer(GravityCompat.START);
}
});
// 设置各菜单的点击事件(方式一)
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int id = item.getItemId();
String tip = "";
switch (id) {
case R.id.action_search:
tip = "搜索";
break;
case R.id.action_setting:
tip = "设置";
break;
case R.id.action_help:
tip = "帮助";
break;
}
Toast.makeText(ToolbarActivity.this, tip, Toast.LENGTH_SHORT).show();
return false;
}
});
}
设置 ActionMenu 和设置 点击事件以上是第一种方式,还可以使用以下方式,效果一样
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 设置ActionMenu布局(方式二)
getMenuInflater().inflate(R.menu.menu_toobar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
String tip = "";
switch (id) {
// 对应 NavigationIcon 的点击
case android.R.id.home:
tip = "菜单";
break;
case R.id.action_search:
tip = "搜索";
break;
case R.id.action_setting:
tip = "设置";
break;
case R.id.action_help:
tip = "帮助";
break;
}
Toast.makeText(ToolbarActivity.this, tip, Toast.LENGTH_SHORT).show();
return false;
}
重写 Activity 的 onCreateOptionsMenu
和 onOptionsItemSelected
方法即可
到此已经实现了一开始所看到的效果
使用中的一些坑
ActionMenu 无法显示
如果我们在代码中调用了setSupportActionBar
方法设置了 Toolbar,此时如果使用第一种方式(mToolbar.inflateMenu(R.menu.menu_toobar)
)创建 ActionMenu 则会导致无法显示,需使用第二种方式(重新 onCreateOptionsMenu)来创建 ActionMenu 才可以mToolbar.setTitle 不生效
如果先调用了setSupportActionBar
方法后,再调用mToolbar.setTitle("title")
来设置 title 的话会导致无法生效,需先调用mToolbar.setTitle("title")
再调用setSupportActionBar
才能生效NavigationIcon 与右侧内容间距太大
这个问题应该挺多人遇到过,其实可以通过在 xml 给 Toolbar 设置app:contentInsetStartWithNavigation="0dp"
或在代码中使用setContentInsetStartWithNavigation(int)
方法进行设置,来控制NavigationIcon 与右侧内容的间距
结语
本文只是简单地介绍了 Toolbar 和其使用,虽然该控件已经很完善了,不过实际开发中还是为自定义导航栏为主,主要方便扩展,想了解 Toolbar 的更多介绍以及相关 API 请参考官方文档(需要梯子),本文 demo 已上传到 github