在使用ActionBar的时候,一堆的问题:这个文字能不能定制,位置能不能改变,图标的间距怎么控制神马的,由此暴露出了ActionBar设计的不灵活。

在上一篇中,我们只是简单使用了AppCompatActivity,他使用的仍然是ActionBar
官方在21以后提供了ToolBar。
Toolbar之所以灵活,是因为它其实就是一个ViewGroup,我们在使用的时候和普通的组件一样,在布局文件中声明。

主题使用

使用Toolbar时,如果单纯的当作控件来使用,主题是不需要单独设置的。
但是如果想用他来替代ActionBar,
那么需要配置为Theme.AppCompat.NoActionBar主题,
或者在主题中加入

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>

(两个都必须有,上一篇已经提到没有windowNoTitle时会报错)
这里推荐使用第一种方式。

常用的配置

Toolbar因为经常被用来替代ActionBar,所以一般项目里都会抽取出来,以便include。
可能有人会说,既然还是用来替换ActionBar,那我项目里直接不动ActionBar不就完了?
对,一般情况下是没有问题的,但是有些界面需要借助Toolbar灵活性的时候,你就被迫要换成Toolbar了。
先来看Toolbar常用代码:

include_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:minHeight="?attr/actionBarSize" />

配置中需要注意的是theme和popupTheme,我们来仔细看下,先从View的theme说起。

View的theme

Android 5.0引入一个全新的特性,允许你对view设置theme,这种设置会影响控件及其包含的子控件。
使用AppCompat v22.1.x 后,也可以给你 layout 里的任意视图设置主题。
只要使用 android:theme 这个属性就好,新版本的兼容库可以在 compat 和 framework 之间无缝地切换功能。

实现原理

这是因为有ContextThemeWrapper类,这个类API v1的时候就有了。
他包裹(wrap)一个存在的Context(这里指你的Activity),之后覆盖(overlay)一个新的主题在当前Context的主题之上,这也是为什么叫ThemeOverlay。

Toolbar常用的ThemeOverlay

  • ThemeOverlay.AppCompat.Light.ActionBar
  • ThemeOverlay.AppCompat.Dark.ActionBar

android:theme 与 app:theme

在AppCompat v21里,提供了一个快速方便的方法设置Toolbar的主题,使用app:theme。

而新版本22.1.x中,AppCompat 允许对 Toolbar 使用android:theme代替app:theme
最好的一点是:它会自动继承父视图的theme ,并且兼容所有APIv11以上的设备。
示例:

<Toolbar
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"><!-- This TextView inherits its theme from the parent Toolbar --><TextView android:text="I'm light!" /></Toolbar>

对于运行 API v10 甚至更老的设备来说,你也可以使用android:theme属性, 不过它不会继承父视图theme。
这就意味着你要么重新考虑你的布局,要么为每一个子视图都设置上 android:theme 属性。(这样做效率真的很低)

总结一下:

  • 兼容 API 11 以上,推荐使用android:theme
  • 如果兼容更老的版本,推荐继续使用app:theme

app:popupTheme

有时候我们有需求:

ActionBar文字是白的,ActionBar Overflow弹出的是白底黑字

让ActionBar文字是白的,那么对应的theme肯定是Dark。
可是让ActionBar弹出的是白底黑字,那么需要Light主题。
这时候popupTheme就派上用场了。

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    android:minHeight="?attr/actionBarSize" />

注意:
使用app:popupTheme="@style/ThemeOverlay.AppCompat.Light"而不是android:popupTheme

作为ActionBar使用

@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.blah);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar);
}

独立使用

@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.blah);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);// Set an OnMenuItemClickListener to handle menu item clickstoolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {@Overridepublic boolean onMenuItemClick(MenuItem item) {// Handle the menu itemreturn true;}});// Inflate a menu to be displayed in the toolbartoolbar.inflateMenu(R.menu.your_toolbar_menu);
}

一般使用疑问

1. 没有了splitActionBarWhenNarrow,用两个Toolbar模拟是否可以?

不可以,这种方式是有问题的。
两个Toolbar放在布局中后,下面的Toolbar不能顶到最左边。
stackoverflow : How to center action menu on toolbar 中有详细的描述。
问题中给出了SplitToolbar的解决方案,但我尝试后发现这种解决方案仍然有轻微的偏移。

2. 使用Toolbar后,NavigationIcon不垂直居中?

Toolbar的layout_height属性,要用“?attr/actionBarSize”而不是“?android:attr/actionBarSize”,替换后可解决NavigationIcon不垂直居中的问题。
原因是系统的actionBarSize比AppCompat中的要小。使用“?android:attr/actionBarSize”调用了较小的那个。

ActionMode配置

使用AppCompatActivity启动

需要声明的是,这种方法更加简便一些,有无Toolbar都适合使用。(感谢dongorigin指正)
直接在AppCompatActivity或者ActionBarActivity中调用startSupportActionMode启动即可。
注意这里的ActionMode是support包里的ActionMode。
这时如果你运行程序触发ActionMode,可能会看到ActionMode和ActionBar分立成两栏,并没有浮在ActionBar上面。
解决的办法很简单,在主题中加入

<item name="windowActionModeOverlay">true</item>

即可。

给ActionMode配置主题

有些同学使用了Dark主题下的Toolbar,并且主题使用了Theme.AppCompat.Light.NoActionBar,这时候会发现ActionMode是Light主题,很难看。
那么怎么能配置成Dark主题呢?

<item name="actionBarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>

弹出菜单自定义主题

<item name="actionBarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>

ActionMode背景色替换

<!--action Mode背景-->
<item name="actionModeBackground">@color/theme_color_action_mode</item>

使用Toolbar启动

代码示例:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.startActionMode(mActionModeCallback)

注意这里的ActionMode是view包下的,不是support v7下的。

保证ActionMode浮在ActionBar上及ActionMode背景色替换与上面方式一致,这里不再赘述,请参考上文。

如何实现和Inbox一样的ActionMode

可以看到,ActionMode开启时,顶部的Status Bar颜色也跟着改变了

这种功能Theme中并没有提供属性来修改。
但是联想到入门篇提到的代码设置status bar颜色,这里就不难实现了。

代码共享下:

private int mOldStatusBarColor = -1;
private void setActionModeStatusBarColor(int colorResId) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mOldStatusBarColor = mActivity.getWindow().getStatusBarColor();setStatusBarColorCore(mActivity.getResources().getColor(colorResId));}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setStatusBarColorCore(int color) {mActivity.getWindow().setStatusBarColor(color);
}
private void resetStatusBarColor() {if (mOldStatusBarColor != -1 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){setStatusBarColorCore(mOldStatusBarColor);mOldStatusBarColor = -1;}
}

开启时调用set,销毁时调用reset即可。

P.S. : 上面的计数可以通过setTitle来完成。

网上提供的错误方式(已踩坑,请绕行)

保持Activity调起,使用android:windowActionModeOverlay属性。
看似让ActionMode浮在了ActionBar上,但其实存在很大问题。
这种方式在4.4以下会使用Holo风格(overflow图标可以看出来,不是三个原点,是三个方块),且ActionMode比ActionBar小一些(可以看到蓝色底边是ActionBar)

其他Material适配必备贴

常用效果及实现

  • How do I use DrawerLayout to display over the ActionBar/Toolbar and under the status bar?
  • A basic sample which shows how to use SlidingTabLayout to display a custom ViewPager title strip which gives continuous feedback to the user when scrolling.
  • [Material Design]使用Toolbar + DrawerLayout快速实现高大上菜单侧滑

官方参考App及示例

  • philm
  • android-UniversalMusicPlayer
  • iosched
  • New Code Samples for Lollipop

参考资料

  • AppCompat v21 — Material Design for Pre-Lollipop Devices!
  • Material Design on Android Checklist
  • Material Design Everywhere: Using AppCompat 21
  • AppCompat 21实现低版本手机使用Material Design
  • Theme vs Style
  • Android 5.x Theme 与 ToolBar 实战
  • Android记录23-关于actionbar中overflow menu(溢出菜单)中的一些问题 http://blog.csdn.net/wwj_748/article/details/44588649

ActionBar -- Toolbar相关推荐

  1. Android Material Design之Toolbar与Palette

    转:http://blog.csdn.net/jdsjlzx/article/details/41441083 前言 我们都知道Marterial Design是Google推出的全新UI设计规范,如 ...

  2. Android Material Design之Toolbar与Palette实践

    转载请注明出处:http://blog.csdn.net/bbld_/article/details/41439715 [Rocko's bog] 前言 我们都知道Marterial Design是G ...

  3. FrameWork之旅 -- Activity过去的门面ActionBar

    本系列的阅读,前提你是一个Android开发者,而且是一个app开发,并且有一定的工作经验.本系列的学习,不会每个细节都说明,会把有"看点"的地方加以说明. 如果你不是Androi ...

  4. 如何使用DrawerLayout在操作栏/工具栏上方和状态栏下方显示?

    本文翻译自:How do I use DrawerLayout to display over the ActionBar/Toolbar and under the status bar? I've ...

  5. 动脑2017android_您肯定要在2017年初尝试的25个新Android库

    动脑2017android by Michal Bialas 由Michal Bialas 您肯定要在2017年初试用的25个Android库 (25 Android libraries you de ...

  6. 原生Android 侧滑菜单实践(部分)

    此为第一个制作侧滑菜单的实践 . 此部分仅仅为部分实践: 仅缺menu的字符串布局,以及需要修改的MainActivity.java文件,也是需要主要修改的地方. 从使用MD设计-进行侧滑菜单的制作( ...

  7. html第2天课堂笔记,第二天课堂笔记

    ##5.0新特性 ###十大新特性 1.全新Material Design设计风格 * 新的视觉语言,在基本元素的处理上,借鉴了传统的印刷设计,字体版式.网格系统.空间.比例.配色.图像使用等这些基础 ...

  8. android 沉浸式状态栏 兼容低版本,详解Android沉浸式实现兼容解决办法

    自android5.0开始,沉浸式状态栏似乎成为一种潮流,应用里缺少沉浸式总感觉少些什么.于是乎,我开始到处找如何兼容低版本的沉浸式,由于Android平台跨度问题,总遇到一些不如人意的问题.终于,皇 ...

  9. android 工具栏透明,Android 系统状态栏沉浸式/透明化完整解决方案

    前言 网上已经有很多有关于系统状态栏的解决方案,这篇文章也不会有什么新奇的解决方案,都是本人经过自己试验,统计提炼出来的相对靠谱的一套解决方案. 如果是android大牛可以忽略本文,怕让您贱笑.只面 ...

最新文章

  1. Android怎么自定义listview布局,android – 如何将listView标头添加为自定义布局
  2. python游戏脚本实例-基于Python实现的扫雷游戏实例代码
  3. python2中为什么在进行类定义时最好要加object
  4. (56)等待链表,调度链表
  5. redhat7防火墙关闭_Linux7关闭防火墙
  6. 系统思考与《第五项修炼》
  7. 8321r 当前不允许登陆_Apache Shiro安全框架实现身份认证(登陆与登出)
  8. HDU 5890 Eighty seven(DP+bitset优化)
  9. 小心使用tf.image.resize_images,填坑经验分享给你
  10. mac 黑窗口连接mysql_python操作mysql数据库
  11. mysql异机还原_MySQL innobackupex全量备份恢复
  12. Linux:计划任务之at
  13. 阿里云服务器如何使用
  14. 计算机里没有硬盘 右下角有图标,电脑右下角显示硬盘图标怎么去掉<br?电脑 – 手机爱问...
  15. 番外9福冈·狂野老司机告诉你如果装AI·1· ——混合现实科幻《地与光》
  16. WDI面板数据(1990-2020)
  17. 一步步教您搞定讯飞语音识别 | 寻找C站宝藏
  18. 那些年你用过最好的键盘
  19. 如何在Ubuntu下使用全民wifi?
  20. 新兴媒体舆情传播动态实时监测的技术解决方案

热门文章

  1. Feign Hystrix微服务调用Session传播
  2. c语言学习进阶-C语言程序稳定性测试
  3. hashtable允许重复吗_在单位缴职工医保,老家有居民医保,能同时报销吗?相关部门这样回应...
  4. OpenShift 4 - 锁定被保护的 OpenShift 资源,禁止删除和修改操作
  5. OpenShift Security (12) - 用 RHACS 管理容器之间的网络访问策略
  6. (四)Raspberry Pi上的人工智能人脸检测
  7. Blazor验证控件
  8. ONNX系列七 --- 在Python中使用可移植的ONNX AI模型
  9. Ubuntu 20.04 LTS(Focal Fossa)发布
  10. OpenJS 基金会推出 Node.js 证书,JS 开发者可以“考证”了