过年前发了一篇介绍 Translucent System Bar 特性的文章 Translucent System Bar 的最佳实践,收到不少开发者的关注和反馈。今天开始写第二篇,全面的介绍一下 Toolbar 的使用。提及 Toolbar ,可能有不少开发的童鞋还比较陌生,不要紧,请接着往下看。android
Toolbar 是在 Android 5.0 开始推出的一个 Material Design 风格的导航控件 ,Google 很是推荐你们使用 Toolbar 来做为Android客户端的导航栏,以此来取代以前的 Actionbar 。与 Actionbar 相比,Toolbar 明显要灵活的多。它不像 Actionbar 同样,必定要固定在Activity的顶部,而是能够放到界面的任意位置。除此以外,在设计 Toolbar 的时候,Google也留给了开发者不少可定制修改的余地,这些可定制修改的属性在API文档中都有详细介绍,如:git
总之,与 Actionbar 相比,Toolbar 让我感觉到Google满满的诚意。怎样?是否已经对 Toolbar 有大概的了解,跃跃欲试的感受出来了有木有?接下来,咱们就一步一步的来看如何使用 Toolbar(实际上是我使用 Toolbar 踩坑填坑的血泪史,大家接下去看,我先擦个眼泪.... )。github
前面提到 Toolbar 是在 Android 5.0 才开始加上的,Google 为了将这一设计向下兼容,天然也少不了要推出兼容版的 Toolbar 。为此,咱们须要在工程中引入 appcompat-v7 的兼容包,使用 android.support.v7.widget.Toolbar 进行开发。下面看一下代码结构,一样把重点部分已经红圈圈出:bash
ToolbarActivity 包含了 Toolbar 的一些基本使用, ZhiHuActivity 是在熟悉了 Toolbar 后对知乎主页面的一个高仿实现。app
layout和menu文件夹分别是上面提到的两个Activity的布局文件 和 actionmenu 菜单文件。ide
values、values-v1九、values-v21 中包含了一些自定义的 theme,后面用到的时候会顺带讲解。布局
咱们先来看一下 ToolbarActivity 的运行效果字体
按照效果图,从左到右分别是咱们前面说起到的 导航栏图标、App的logo、标题和子标题、自定义控件、以及 ActionMenu 。接着,咱们来看下布局文件和代码实现。优化
首先,在布局文件 activity_tool_bar.xml 中添加进咱们须要的 Toolbar 控件ui
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da">
<!--自定义控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
复制代码
接着在 base_toolbar_menu.xml 中添加 action 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/action_search"
android:icon="@mipmap/ic_search"
android:title="@string/menu_search"
app:showAsAction="ifRoom" />
<item
android:id="@id/action_notification"
android:icon="@mipmap/ic_notifications"
android:title="@string/menu_notifications"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_item1"
android:title="@string/item_01"
app:showAsAction="never" />
<item
android:id="@+id/action_item2"
android:title="@string/item_02"
app:showAsAction="never" />
</menu>
复制代码
最后到 ToolbarActivity 中调用代码拿到这 Toolbar 控件,并在代码中作各类setXXX操做。
/**
* Toolbar的基本使用
*/
public class ToolBarActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tool_bar);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//设置导航栏图标
toolbar.setLogo(R.mipmap.ic_launcher);//设置app logo
toolbar.setTitle("Title");//设置主标题
toolbar.setSubtitle("Subtitle");//设置子标题
toolbar.inflateMenu(R.menu.base_toolbar_menu);//设置右上角的填充菜单
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int menuItemId = item.getItemId();
if (menuItemId == R.id.action_search) {
Toast.makeText(ToolBarActivity.this , R.string.menu_search , Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_notification) {
Toast.makeText(ToolBarActivity.this , R.string.menu_notifications , Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_item1) {
Toast.makeText(ToolBarActivity.this , R.string.item_01 , Toast.LENGTH_SHORT).show();
} else if (menuItemId == R.id.action_item2) {
Toast.makeText(ToolBarActivity.this , R.string.item_02 , Toast.LENGTH_SHORT).show();
}
return true;
}
});
}
}
复制代码
代码到此已经完成了 Toolbar 的基本使用,注意,是基本使用而已!!!!!下面有几个代码里面须要注意的地方:
咱们在使用 Toolbar 时候须要先隐藏掉系统原先的导航栏,网上不少人都说给Activity设置一个NoActionBar的Theme。但我的以为有点小题大作了,因此这里我直接在BaseActivity中调用 supportRequestWindowFeature(Window.FEATURE_NO_TITLE) 去掉了默认的导航栏(注意,个人BaseActivity是继承了AppCompatActivity的,若是是继承Activity就应该调用requestWindowFeature(Window.FEATURE_NO_TITLE));
若是你想修改标题和子标题的字体大小、颜色等,能够调用setTitleTextColor、setTitleTextAppearance、setSubtitleTextColor、setSubtitleTextAppearance 这些API;
自定义的View位于 title、subtitle 和 actionmenu 之间,这意味着,若是 title 和 subtitle 都在,且 actionmenu选项 太多的时候,留给自定义View的空间就越小;
导航图标 和 app logo 的区别在哪?若是你只设置 导航图标( or app logo) 和 title、subtitle,会发现 app logo 和 title、subtitle 的间距比较小,看起来不如 导航图标 与 它们两搭配美观;
Toolbar 和其余控件同样,不少属性设置方法既支持代码设置,也支持在xml中设置(这里也是最最最最最坑爹的地方,如何坑爹法,请接着往下看);
刚开始使用Toolbar的时候,个人布局文件中是这样写的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
android:logo="@mipmap/ic_launcher"
android:navigationIcon="@mipmap/ic_drawer_home"
android:subtitle="456"
android:title="123">
<!--自定义控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
复制代码
在真机跑起来以后,看到的结果是下面这样的。
此时心中真是万千匹草泥马在奔腾,除了设置背景色和TextView有效外,说好的 logo、navigationIcon、subtitle、title 都跑哪去了?在编译器没报错又不见效果的状况下,参考了其余开发者的用法后找到了如下的解决方案,就是在根布局中加入自定义属性的命名空间
xmlns:toolbar="http://schemas.android.com/apk/res-auto"(这里的toolbar能够换成你想要其余命名,作过自定义控件的童鞋相比很熟悉此用法了)
复制代码
而后把全部用 android:xxx 设置无效的,都用 toolbar:xxx 设置便可生效。最终的布局代码以下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
toolbar:navigationIcon="@mipmap/ic_drawer_home"
toolbar:logo="@mipmap/ic_launcher"
toolbar:subtitle="456"
toolbar:title="123">
<!--自定义控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
</LinearLayout>
复制代码
到此便可解决 xml 中属性设置失效的问题,为何会出现这种问题呢?我猜想是由于这个控件是兼容版的控件,用 android:xxx 设置无效是的这些属性是在兼容包中,不在默认的Android SDK中,因此咱们须要额外的引入。至于为何IDE不报错,估计就是bug了吧!
系统默设置了ActionMenu每一个Item的文字颜色和大小,像ToolbarActivity在Google原生5.1系统下默认效果就是下面这样的
此时,若是我有需求要改变一下item文字颜色,应该怎么破?我按照网上比较广泛的解决方案,作了以下两步的修改操做:
<style name="Theme.ToolBar.Base" parent="Theme.AppCompat.Light.NoActionBar">
<item name="actionMenuTextColor">@color/color_red</item>
</style>
复制代码
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
toolbar:popupTheme="@style/Theme.ToolBar.Base">
<!--自定义控件-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clock" />
</android.support.v7.widget.Toolbar>
复制代码
运行以后,文字的颜色的并无发生任何改变。说好的改变颜色呢.....找来找去,最后在 StackOverflow 找到一个还不错的解决方案,就是把上面的的 actionMenuTextColor 属性换成 android:textColorPrimary 便可解决,最终获得下面的运行效果。
这种方法也有一个小缺点,若是我把自定义控件换成Button,你会发现Button默认的文字颜色也变成了红色。因此,此处若是有朋友有更好的解决方案,请留言赐教。
若是你想要修改 ActionMenu Item 的文字大小,也能够在theme中设置加上以下设置
<item name="android:textSize">20sp</item>
复制代码
以上就是目前使用 Toolbar 一些比较折腾的坑,感受 Google 对 Toolbar 这些坑,还能够进一步优化优化,否则就坑苦了开发者们了。
为了加深一下 Toolbar 的开发体验,咱们使用 Toolbar 来实现知乎主页的效果!先来看下知乎主页的效果
若是前面的内容你看明白,想撸出这个界面无非是几分钟的事情,下面就直接上代码,不作赘述了。
ZhiHuActivity界面代码
public class ZhiHuActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zhi_hu);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.zhihu_toolbar_menu);
toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);
toolbar.setTitle(R.string.home_page);
toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
}
}
复制代码
zhihu_toolbar_menu.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/action_search"
android:icon="@mipmap/ic_search"
android:title="@string/menu_search"
app:showAsAction="ifRoom" />
<item
android:id="@id/action_notification"
android:icon="@mipmap/ic_notifications"
android:title="@string/menu_notifications"
app:showAsAction="ifRoom" />
<item
android:id="@id/action_settings"
android:orderInCategory="100"
android:title="@string/menu_settings"
app:showAsAction="never" />
<item
android:id="@id/action_about"
android:orderInCategory="101"
android:title="@string/menu_about_us"
app:showAsAction="never" />
</menu>
复制代码
activity_zhi_hu.xml 布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_0176da"
android:theme="@style/Theme.ToolBar.ZhiHu">
</android.support.v7.widget.Toolbar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@mipmap/ic_zhihu_logo" />
</RelativeLayout>
</LinearLayout>
复制代码
styles.xml 中的 Theme.ToolBar.ZhiHu,给 Toolbar 设置android:theme用的
<resources>
...
...
<style name="Theme.ToolBar.ZhiHu" parent="Theme.AppCompat.Light.NoActionBar">
<item name="actionOverflowButtonStyle">@style/ActionButton.Overflow.ZhiHu</item>
</style>
<style name="ActionButton.Overflow.ZhiHu" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
<item name="android:src">@mipmap/ic_menu_more_overflow</item>
</style>
</resources>
复制代码
最终获得下面这样的效果
这里在 Toolbar 设置 android:theme="@style/Theme.ToolBar.ZhiHu" 主要是为了替换系统右上角三个点的图标,若是不设置,则会成系统默认主题的样子。
最后,再给知乎的主页面作个小小的优化,它在 Android 4.4 上运行仍是可以看到一条黑乎乎的通知栏,为此我把 Toolbar 和 Translucent System Bar 的特性结合起来,最终改进成下面的效果(附上 Android4.4 和 5.1 上的运行效果)。
若是你还不知道 Translucent System Bar 的特性怎么使用,请查看个人上一篇文章:Translucent System Bar 的最佳实践
关于 Toolbar 的使用就介绍到此,原本是怀着很简单就能够上手的心态来使用,结果发现仍是有不少坑须要填。果真仍是验证了一句老话
纸上得来终觉浅,绝知此事要躬行
复制代码
一样,分享即美德,须要源代码的童鞋,请戳:github.com/D-clock/And…
做者:D_clock爱吃葱花
连接:www.jianshu.com/p/79604c3dd…