Android 主题设计全解析
Posted 痕迹天涯119
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 主题设计全解析相关的知识,希望对你有一定的参考价值。
android主题设计!有点乱?
初学Android的时候对Android的主题设计都是处在一种模糊的认知状态,为啥呢?
自定义时候的attr,普通view的style属性,activity以及application的theme属性,theme与style定义的一致性以及theme的众多可选性,系统预置的style属性的继承与使用等等……
OK,先不管这些乱七八糟的,如果你对Android的主题设计依旧存在某些疑问,请看完这篇文章。
Theme、Style、Attr的基本概念
Attr:属性,风格样式的最小单元;
Style:风格,它是一系列Attr的集合用以定义一个View的样式,比如height、width、padding等;
Theme:主题,它与Style作用一样,不同于Style作用于个一个单独View,而它是作用于Activity上或是整个应用,并具有向下的覆盖特性
Theme
Theme的概念验证
好吧,为了清晰的验证上面的说法,我这里举个例子
新建一个moudle,在styles.xml中有如下内容
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
可以看到该style定义了该主题下共享的三个颜色属性,以及继承了一个父主题
那么来看一下该主题应用的代码
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
此时 ,这个默认主题应用在了Application下,我们启动模拟器观看主题效果
普普通通没啥特别的,我们为前面的主题添加两个属性
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
重新启动模拟器,你看到了什么
Activity的ActionBar被隐藏了,
是的,正如我前面所说,Theme一般应用于Application和Activity层级,并会继续向下覆盖,这里我们虽然只是设置了Application的theme属性,其下的所有Activity都会使用该主题。
Theme的定义
Theme的定义基本是一致的,主要是外部由一个一对style标签,内部通过item指明所定义的各个属性,下面的Theme就是一个标准的样例,
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
Theme的继承
1)通过parent属性进行系统主题的继承
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
2)通过“.”进行自定义主题的继承
<style name="AppTheme.NoActionbar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
“.”前面是我们自定义的主题name,后面那就随意了,怎么写都可以了
style的继承与Theme一致,如果你原来不明白别人为何这样写,那么现在你肯定是知道了
Theme和Style的区别
- 定义上的区别:无太大区别,主要是属性不同,写法上基本一致
- 使用上的区别:
对于单个控件通过style进行引入(此时style不会向下覆盖);
对于Activity、Application等窗口级向下应用的通过theme进行引入;
使用系统预置的style
<!-- 使用系统预制style -->
<activity android:theme="@android:style/Theme.Dialog">
<!-- 使用系统预制但局部修改的style -->
<activity android:theme="@style/CustomTheme">
<color name="custom_theme_color">#b0b0ff</color>
<style name="CustomTheme" parent="android:Theme.Light">
<item name="android:windowBackground">@color/custom_theme_color</item>
<item name="android:colorBackground">@color/custom_theme_color</item>
</style>
使用Android系统内置的style,请务必加上“android:”
ThemeOverlays
在所有可用的主题中,我们可以发现一个名字带有 ThemeOverlay 的系列:
ThemeOverlay
ThemeOverlay.Light
ThemeOverlay.ActionBar.Light
ThemeOverlay.ActionBar.Dark
这些主题又是做什么的呢?答案是 仅用于为特定的用途定义必要的属性。
如果你不清楚,请看测试
我们首先创建两个toolbar的style
<style name="AppTheme.AppBar1" parent="ThemeOverlay.AppCompat.Light"/>
<style name="AppTheme.AppBar2" parent="ThemeOverlay.AppCompat.Dark"/>
添加toolbar进行测试
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:theme="@style/AppTheme.AppBar1"
android:background="@color/colorPrimary"/>
修改为第二个
通过改变主题我们可以很轻松的实现界面的View的样式变换,是不是会很方便。
Theme的选用
其是很简单,在MD设计(也就是5.0)被推出之后,google推出了几个material的主题,但你不必去使用这些主题,因为有更好的替代方案
Theme.AppCompat
Theme.AppCompat.Light,
Theme.AppCompat.NoActionBar等等
这些主题既保证了向下的兼容又兼顾了material的主题设计,并与materiial的各个主题一一对应,你在选择的时候使用以Theme.AppCompat开头的主题准是没错。
那就有人问了,为毛线这么干,其他乱七八糟的主题又是啥呢?
这里我强烈推荐你看一篇文章(译文):android-themes-an-in-depth-guide
Attr
首先以layout_width为例分析自定义属性
<declare-styleable name="ViewGroup_Layout">
<attr name="layout_width" format="dimension">
<enum name="fill_parent" value="-1" />
<enum name="match_parent" value="-1" />
<enum name="wrap_content" value="-2" />
</attr>
</declare-styleable>
declare-styleable
代表自定属性组,attr则是代表属性,name是属性的标识,format是该属性的值类型,内部为enum表示值是唯一的,只可选其一。
再来看一下text的style
<attr name="textStyle">
<flag name="normal" value="0" />
<flag name="bold" value="1" />
<flag name="italic" value="2" />
</attr>
此时attr的内部是flag,代指属性值是可叠加使用的,比如textStyle = bold|italic
则是加粗和斜体的叠加。
format属性的可选值如下
其中,reference代表引用,我们常用的@drawable/myImage、@color/myColor
等都是这么干的。
ok,attr内部也只有enum和flag两种类型的属性,看完这个相信你可以自行定义属性了。
特别注意,当你的format选择错误的时候,填入对应的值AS并不会报错,所以具体实践时请留心
Attr的获得方法
有些情况下,我们可能需要使用theme中的属性值,比如下面我们想让一个TextView直接显示dogName这个属性的内容,并且使用系统字体的颜色,则可以如下做:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:textColorSecondary"
android:text="?attr/dogName"/>
获得一个Attr的方法,不同于普通资源使用@符号获得的方式,而是需要使用?符号来获得属性,整体的表达方式如下:
?[:][/]
如果是本应用中的attr使用,则可以省去<package_name>
部分。
此处的textColor使用当前主题的android:textColorSecondary属性内容。因为资源工具知道此处是一个属性,所以省去了attr (完整写法:?android:attr/textColorSecondary)。
Attr的使用优先级:View的Style>Activity的Theme>Application的Theme,所以说你可以定义整个应用的总体风格,但局部风格你也可以做出自己的调整。
最近做了下反思,与其制造网络垃圾不如不去写文章,所以准备大幅度降低写作速度并致力于提升文章的质量,未来计划在自己进步的同时分享进步的干货并不断去删除原文,以保证整个博客的文章质量和可用性。
如果你对本文有什么问题和看法请及时告知,送人玫瑰手有余香,谢谢支持。
参考文章:
Attr、Style和Theme详解
Android开发之Theme、Style探索及源码浅析
ThemeOverlay
Android Themes — An in-depth guide
以上是关于Android 主题设计全解析的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 和 Android Studio,Eclipse等安卓开发工具比怎么样