菜单

Android Theme.AppCompat 中,你应该熟悉的颜色属性

2020年1月15日 - 金沙国际唯一官网
Android Theme.AppCompat 中,你应该熟悉的颜色属性

金沙国际棋牌下载官网,Android 5.0 可以给一个 View 单独设置一个 theme 了,其主要用途就是用在
ToolBar 上, 比如 当前使用白色主题但是想使用黑色的 ToolBar ,只要在
ToolBar 的 xml 文件
中添加 android:theme=”@android:style/ThemeOverlay.Material.Dark.ActionBar”
即可。

金沙国际唯一官网 1

继续Material系列,先从Toolbar讲起

<Toolbar  
    android:layout_height="?android:attr/actionBarSize"
    android:layout_width="match_parent"
    android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar" />

创建一个 Android 工程,第一步,也是必不可少的一步,就是定制 Application
主题样式。利用系统诸多属性定义 App 各种 View 的默认样式,能够减少 layout
文件中很多重复性的属性设置代码。在开发者官网 R.attr 栏目中,Google
列出了所有 Android SDK
中的系统级属性。如何取舍,如何区分,又有哪些常用的属性呢?本文就来列举颜色相关的一些属性介绍,以供参考。

ActionBar –> Toolbar

在使用ActionBar的时候,一堆的问题:这个文字能不能定制,位置能不能改变,图标的间距怎么控制神马的,由此暴露出了ActionBar设计的不灵活。
在上一篇中,我们只是简单使用了AppCompatActivity,他使用的仍然是ActionBar
官方在21以后提供了ToolBar。
Toolbar之所以灵活,是因为它其实就是一个ViewGroup,我们在使用的时候和普通的组件一样,在布局文件中声明。

该功能在 5.0 之前也存在,只是无法单独在 View 上设置而已,比如
5.0之前的 Theme.Holo.Light.DarkActionBar 主题,就是白色主题但是
ActionBar
是黑色。这种底层实现方式是通过一个 actionBarWidgetTheme 来引入一个新的主题。

金沙国际唯一官网 2

主题使用

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

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

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

<style name="Theme.Holo.Light.DarkActionBar">
    <item name="android:actionBarWidgetTheme">@android:style/Theme.Holo</item>
</style>

通常,在 res/values/styles.xml 文件中定义的 application
主题样式里,你可能见到的最常见的使用组合是这样:

常用的配置

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说起。

底层实现细节

底层是通过 ContextThemeWrapper 类实现的,顾名思义该类所做的工作就是在当前
context 上装饰另外一个 theme,来覆盖(改变)一些控件的属性。

金沙国际唯一官网,因此,在 5.0 中又引入了一种新的 theme – ThemeOverlay ,主要有这么两种:

分别为 白色 和黑色的。把这两个 theme 装饰到 Theme.Material
上来修改部分的样式为白色或者黑色。同样,对于特殊的 ActionBar
而言,也有两个衍生出来的 ThemeOverlay theme:

这两个 theme 应该只使用在 5.0 的新
属性actionBarTheme 或者 Toolbar 上(上面的 xml 代码示例)。 这两个
theme
目前只是把  colorControlNormal 修改为``android:textColorPrimary 的值并把所有的文字和图标都设置为不透明的。

<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style></resources>

View的theme

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

android:theme

android:theme 是 5.0 中新添加到 View 上的属性。需要注意的是,
该属性会传递给所有子控件,例如:

<LinearLayout
    android:theme="@android:style/ThemeOverlay.Material.Dark">

    <!--这里面的所有 view 都会使用 ThemeOverlay.Material.Dark theme,除非你在单独给某个 view 设置一个新的 theme 属性  -->

</LinearLayout>

5.0 还引入了一个新的 theme 属性: colorEdgeEffect ,该属性可以定制一个
View 过度滑动的(颜色)效果, 通过上面的 方式可以很容易的修改一个 View
的 过度滑动效果;

由于这是一个 theme 里面的 属性,所以无法直接应用到 View
上,我们可以自定义一个 Overlay theme,
在里面设置 colorEdgeEffect 的值,然后在 View 上通过 android:theme
属性来设置这个自定义的 theme 即可。

自定义theme res/values/themes.xml

<style name=”RedThemeOverlay” parent=”android:ThemeOverlay.Material”>
<item name=”android:colorEdgeEffect”>#FF0000</item>
</style>

然后把该 theme 设置到 view 上:

<ListView … android:theme=”RedThemeOverlay” />

通过上面同样的方式,您可以自定义所有 theme 里面的属性。

事实上,远不止这样…

实现原理

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

Theme VS Style

那么问题来了, Theme 和 Style 到底有啥区别呢?
他们的定义方式是一模一样的,只是使用的地方不一样而已。

Theme 是用来设置应用全局 主题风格的, 5.0 上可以让你局部的调整设计风格;

而 Style 主要是用在 View 上的,当你在 view
上设置 style 的时候,LayoutInflater  会读取 该 style
的内容并在任意单独设置的样式之前把该内容设置到 AttributeSet 中。

总结起来就是: Theme 是全局的;Style 是局部的。

需要注意的是,如果您使用 AppCompat V21 的话,当前 AppCompat
只能在android.support.v7.widget.Toolbar 上使用 Theme 属性。

自 Lollipop 开始,Android 系统引入 Material Design
风格,各个控件的呈现样式大有改变。为了在不同版本的系统中统一 UI
样式,设置自定义的 Application Theme 的 parent 样式为 Theme.AppCompat
系列即可。比如这里的 Theme.AppCompat.Light.NoActionBar 主题。

Toolbar常用的ThemeOverlay

关于 AppCompat
相关主题提供的系统属性,可以参考源码:v7/appcompat/res/values-v21/themes_base.xml。

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 属性。(这样做效率真的很低)

总结一下:

同时,由于部分属性的版本兼容问题,为了避免添加多个版本的 styles
文件,可以省略 android: 命名空间。

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

colorPrimary

作为ActionBar使用

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.blah);

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
}

App Bar 的背景色,即 ActionBar,通常也是一个 App 的主题色调。不过
ActionBar 已经退出历史舞台,由 Toolbar 代替使用,但是 Toolbar 需要在
layout 文件中单独使用 background 属性设置背景色,如:

独立使用

@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);
}
<android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" />

一般使用疑问

colorPrimaryDark

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

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

status bar背景色。仅作用于 Lollipop 及更高版本。

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

金沙国际唯一官网 3

NavigationIcon

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

colorAccent

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>

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图