聊聊Android Theme的那些事
2016-10-24 00:00
155 查看
1. 概述
话说Android里面的主题真是琳琅满目,虽然平时开发时我们都是固定,约定成熟的使用某个主题,例如官方推荐的AppComat系列,但是Android有多少主题,它们之间有什么联系和区别很少人去认真探究。我本人开发时都是直接使用Android Studio生成的主题,或者是继承至它。Holo主题基本没有使用过,似乎是一个比较老的主题,比我早接触Android的前辈们应该比较熟悉。Material主题就属于比较新的主题。还有呢?2. 一些主要的根主题以及它的继承结构
这里我使用了“根主题”的说法,因为大多数主题都是继承至某个主题,追根究底,会找到几个没有parent的根主题。我们来看看这几个根主题:Theme:API 10及其以下的默认主题。
Theme.Holo:API 11 - 13的默认主题,
Theme.Material:API 21及其以上。
2.1 如何追溯到这些Theme?
你可以随便新建一个Theme,parent继承至Theme.AppCompat,按住
Ctrl(在Mac上是
Command)点击parent主题,这样一直追溯到
Platform.AppComat会有几个选择:
到这里,Theme的继承就区别开来了,
/values.xml最终会继承至
Theme,
/values-v11.xml和
/values-v14.xml最终会继承至
Theme.Holo,而
/values-v21.xml会继承至
Theme.Material。所以说,一般我们选择主题选择继承至
AppCompat系列的主题就可以了(至少现在是如此),
AppCompat已经做好适配工作了。
2.2 它们有什么区别呢?
据我所对比观察,它们的参数基本上相同:双方有些细微的增缺,只有值大不一样,但这并不影响什么,我们必要的时候直接去所关心的Theme那里了解一下目标参数。一个主题规范严格的app,风格的定义应该在App Theme上就得到了统一,这些根主题的参数给了我们修改,参考的依据,了解这些参数是很有必要的。
2.3 只有这些根主题吗?
当然,Android系统如此庞杂,远远不止这些根主题,上述3个根主题所在的xml文件里定义了很多根主题,适当了解一下会有好处。2.4 如此多的子主题,我们该如何抉择?看看它的继承结构。
我先贴上一张自己总结的图:我以
AppCompat系列的主题为例,图中并没有将所有主题都收拢进去,毕竟太多了。图中枝节点的依据是这样子:例如
Base.TextAppearance.AppCompat.Widget.Actionbar.Subtitle.Inverse这个style,已
.为分割线,
Base、
TextAppearance...为节点作成的结构图。从图中可以很直观的得出结论:主题分为
TextAppearance、
Theme、
ThemeOverlay和
Widget4种。
TextAppeareance: 定义字体样式。
Theme: 定义Dialog和Application的样式。
ThemeOverlay: 定义悬浮层的样式,例如点击ActionBar上的更多或者下拉菜单弹出的悬浮界面的样式。
Widget:顾名思义,定义
Button之类的组件的样式。
如果你想使用某个字体主题或者自定义,你可以使用或者继承TextAppearance系列:
同样的Theme系列:
ThemeOverlay系列:
Widget系列:
Android的Style命名已经极大的便利我们使用,我们唯一要做的事就是根据业务需求了解某个主题的参数和值,并且在必要的时候复写它。
3 自定义样式
现在用实际行动来验证我们的猜想。我新建了一个Activity,它是这样子:Activity代码:
public class ActionBarActivity extends AppCompatActivity { @Bind(R.id.toolbar) Toolbar mToolbar; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_action_bar); ButterKnife.bind(this); mToolbar.setTitle("Thanatosx"); mToolbar.setSubtitle("Widgets"); setSupportActionBar(mToolbar); ActionBar mActionBar = getSupportActionBar(); if (mActionBar != null){ mActionBar.setDisplayHomeAsUpEnabled(true); mActionBar.setHomeButtonEnabled(false); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menus, menu); return super.onCreateOptionsMenu(menu); } }
Layout布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="#80123456" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
以及Theme主题:
<style name="AppTheme" parent="Theme.AppCompat.Light"> <!-- Customize your theme here. --> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> </style>
现在我们想要通过修改Theme来改变Toolbar的样式达到以下效果:
改变返回图标
改变Title和Subtitle的字体大小和颜色
改变more icon的颜色
首先,第一个问题是:去哪里修改?前面说到,Theme主题基本可以定义一个Application的大部分地方的样式,我们需要去搜索一下父主题是否有这样的定义,从
Theme.AppCompat.Light这个主题开始往上追溯,在
Base.Theme.AppCompat.Light上会有个版本选择:
这个无所谓,选择低版本的就可以了,低版本都支持的话就不用担心高版本,首先会在
Base.v7.Theme.AppCompat.Light上发现Toolbar Style的定义:
那么,我们就可以复写这个属性,自定义我们的Toolbar Style了,同样的,有个
actionOverflowButtonStyle属性,它就是定义more icon button的属性了。
修改后的Theme:
<style name="AppTheme" parent="Theme.AppCompat.Light"> <!-- Customize your theme here. --> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="actionOverflowButtonStyle">@style/AppWidget.ActionButton.Overflow</item> <item name="toolbarStyle">@style/AppTheme.Toolbar</item> </style> <style name="AppTheme.Toolbar" parent="Widget.AppCompat.Toolbar"> <item name="android:minHeight">50dp</item> <item name="titleTextAppearance">@style/AppTextAppearance.Widget.Actionbar.Title</item> <item name="subtitleTextAppearance">@style/AppTextAppearance.Widget.Actionbar.Subtitle</item> <item name="navigationIcon">@mipmap/ic_back</item> <item name="android:background">?attr/colorPrimary</item> </style> <style name="AppTextAppearance.Widget.Actionbar.Title" parent="TextAppearance.Widget.AppCompat.Toolbar.Title"> <item name="android:textSize">14sp</item> <item name="android:textColor">#FFF</item> </style> <style name="AppTextAppearance.Widget.Actionbar.Subtitle" parent="TextAppearance.Widget.AppCompat.Toolbar.Subtitle"> <item name="android:textSize">12sp</item> <item name="android:textColor">#FFF</item> </style> <style name="AppWidget.ActionButton.Overflow" parent="Widget.AppCompat.ActionButton.Overflow"> <item name="android:src">@mipmap/ic_more</item> </style>
parent继承至原使用的Style Theme,以此基础上重写自己需要修改的属性,最终效果图:
4 坑
在修改Activity的返回按钮的时候我在AppTheme里找到这个属性:
homeAsUpIndicator,老司机们肯定明白,这就是设置返回按钮的图标,但是无论我如何设置,修改,这个属性没有任何效果!!无奈之下,我去overflowstack上寻找答案,众说纷纭,倒是看到这个属性
navigationIcon,我在Theme上没看到,在Toolbar的主题上也没有看到,但是当我进入Toolbar的源码,我发现是有这个属性的:
我直接跑去R.java文件去看,一目了然:
源码之下,没有秘密
还有一点,设置
navigationIcon之后,点击返回按钮没有任何响应了,需要设置Navigation Click Listener
// after set support action bar mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } });
相关文章推荐
- android和iphone 那些事
- (zz) 聊聊咨询那些事 1
- Android入门第十六篇之Style与Theme
- 杂乱之android的style、Theme的应用
- Android中Style和Theme的使用
- android全屏设置代码:android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
- Android入门第十六篇之Style与Theme
- android UI进阶之style和theme的使用
- android那些事——android的成长
- (zz) 聊聊咨询那些事 3
- android的换肤(theme)
- Applying Styles and Themes - 应用Style和Theme - Android官方文档中文翻译
- Android中theme的用法
- Android 自带的一些可用于Activity的Theme
- (zz) 聊聊咨询那些事 2
- (zz) 聊聊咨询那些事 5
- Android风格与主题(style and theme)
- Android入门之Style与Theme
- android 自带的主题theme
- Android系统自带theme