版权声明:

欢迎转载,但请保留文章原始出处

作者:GavinCT

出处:http://www.cnblogs.com/ct2011/p/4493439.html

继续Material系列,先从Toolbar讲起

ActionBar --> Toolbar

在使用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 clicks
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// Handle the menu item
return true;
}
}); // Inflate a menu to be displayed in the toolbar
toolbar.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适配必备贴

常用效果及实现

官方参考App及示例

参考资料

Material适配2 - 高级篇的更多相关文章

  1. Material适配1 - 入门篇

    版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/4493384.html 随着Material Design的普 ...

  2. MyBatis高级篇之整合ehcache缓存框架

    MyBatis高级篇之整合ehcache缓存框架  2017-09-01  0 Comments  1,671 Views  0 Times 一.前言 MyBatis为我们提供了Cache接口,也提供 ...

  3. Spring Cloud Alibaba | Sentinel: 服务限流高级篇

    目录 Spring Cloud Alibaba | Sentinel: 服务限流高级篇 1. 熔断降级 1.1 降级策略 2. 热点参数限流 2.1 项目依赖 2.2 热点参数规则 3. 系统自适应限 ...

  4. C#高级知识点&(ABP框架理论学习高级篇)——白金版

    前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...

  5. 【.net深呼吸】动态类型(高级篇)

    前面老周给大家介绍了动态类型使用的娱乐级别用法,其实,在很多情景下,娱乐级别的用法已经满足需求了. 如果,你想自己来控制动态类型的行为和数据的存取,那么,就可以考虑用今天所说的高大上技术了.比如,你希 ...

  6. 【转载】Spark性能优化指南——高级篇

    前言 数据倾斜调优 调优概述 数据倾斜发生时的现象 数据倾斜发生的原理 如何定位导致数据倾斜的代码 查看导致数据倾斜的key的数据分布情况 数据倾斜的解决方案 解决方案一:使用Hive ETL预处理数 ...

  7. ORM查询语言(OQL)简介--高级篇(续):庐山真貌

    相关文章内容索引: ORM查询语言(OQL)简介--概念篇 ORM查询语言(OQL)简介--实例篇 ORM查询语言(OQL)简介--高级篇:脱胎换骨 ORM查询语言(OQL)简介--高级篇(续):庐山 ...

  8. ORM查询语言(OQL)简介--高级篇:脱胎换骨

    相关文章内容索引: ORM查询语言(OQL)简介--概念篇 ORM查询语言(OQL)简介--实例篇 ORM查询语言(OQL)简介--高级篇:脱胎换骨 ORM查询语言(OQL)简介--高级篇(续):庐山 ...

  9. 25个增强iOS应用程序性能的提示和技巧(高级篇)(2)

    25个增强iOS应用程序性能的提示和技巧(高级篇)(2) 2013-04-16 14:56 破船之家 beyondvincent 字号:T | T 在开发iOS应用程序时,让程序具有良好的性能是非常关 ...

随机推荐

  1. java验证码工具

    工具类: package com.lhy.web.servlet; import java.awt.BasicStroke; import java.awt.Color; import java.aw ...

  2. bootstrap table 修改table内容时设置表头与表格对齐

    第一:取消表头初始化解决表头和内容不对齐问题,取消后表头将不固定. 在你对应的js(bootstrap-table.min.js或bootstrap-table.js,我用的bootstrap-tab ...

  3. C++中class的类型转换重载

    注:本文测试实例使用的编译器版本为clang-703.0.29. 我们已经习惯了基本数据类型的显式或隐示转换,如: ; float f = (float)a;float c = a; 其实通过oper ...

  4. java HashMap源码分析(JDK8)

    这两天在复习JAVA的知识点,想更深层次的了解一下JAVA,所以就看了看JAVA的源码,把自己的分析写在这里,也当做是笔记吧,方便记忆.写的不对的地方也请大家多多指教. JDK1.6中HashMap采 ...

  5. 8分钟丨教你玩转 API

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由织云平台团队发表于云+社区专栏 背景 当下,业界越来越多公司在项目架构设计时,会采用微服务架构.微服务架构,可以让我们的产品有更好的扩 ...

  6. SpringMVC 使用 RESTful 架构实现 CRUD 操作

    软件152 余建强 源码下载:http://download.csdn.net/detail/qq_35318576/9826210 1 使用框架 SpringMVC.Maven.Ajax.JSTL. ...

  7. SPA应用部署时首屏启动慢问题解决方案

    SPA应用部署时首屏启动慢问题解决方案 使用vuejs开发的单页应用,打包部署上线后,发现首屏启动时间达到了惊人的10s左右,于是开始优化,目前使用到的总结如下: 巧用webpack插件 1.抽取cs ...

  8. Centos系统下卸载、安装MySQL及用户的创建、授权和使用(详细。。。。)

    由于经常使用linux系统,并且大数据环境搭建中经常会使用到mysql,不像windows系统下的安装,今天有点空写一篇,下面我给大家演示一遍. 主要有三部分内容: 1.MySQL的卸载 2.MySQ ...

  9. SpringMVC的controller层接收来自jsp页面通过<a href="/user/userUpdateInfo/>的中文乱码问题

    这种情况是,jsp页面的中文正常显示,数据的中文也是正常显示,但是在Controller层接收到的中文是乱码,如下图所示: 解决方法:在Controller层对前台传递的中文乱码进行处理,将它转换成u ...

  10. 使用mac下Fiddler的替代工具Charles进行手机抓包

    对手机的抓包有两种方式,各有优劣且互补,一般第一种即可,对于不走代理的 App 选择第二种方式 第一种 Fiddler: 利用 Fiddler 抓包,适合大多数走代理的应用, 优点 (1) 无需 ro ...