前言
样式Style和主题Theme是Android中很重要两个概念,用的时候很容易弄混淆,此篇我准备从自定义属性到自定义样式,了解一下Android里属性,样式和主题的原理。
简介
-
Attr:属性,风格样式的最小单元;
-
Style:风格,它是一系列Attr的集合用以定义一个View的样式,比如height、width、padding等;
-
Theme:主题,它与Style作用一样,不同于Style作用于个一个单独View,而它是作用于Activity上或是整个应用。
View的Style(样式)
假设给自定义View:MyView设定了几个自定义属性:attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="dml">
<attr name="circleColor" format="color|reference"/>
<attr name="circleSize" format="integer"/>
</declare-styleable>
</resources>
然后把这几个属性封装成一个Style:style.xml
<resources>
<style name="editStyle">
<item name="circleColor">#343434</item>
<item name="circleSize">40</item>
</style>
</resources>
在布局文件中给MyView设置style:
style="@style/editStyle"
在MyView的构造方法中获取这些属性:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.dml);
int color = ta.getInt(R.styleable.dml_circleColor,-1);
int size = ta.getInt(R.styleable.dml_circleSize,-1);
Log.d("dml","color = " + color + "-------size = " + size);
}
看下效果:
05-02 21:18:08.626 31441-31441/com.example.app2 D/dml: color = -13355980-------size = 40
- 其实在Android系统中,我们给View设置属性比如TextView设置android:textSize="23sp",在TextView的源码中也是这么在构造方法中获取的,然后在OnDrawI()中绘制,这就是Android的View属性和Style的工作原理。同样,我们在Allication节点设置android:theme属性那么在Activity源码中肯定有方法来获取这个style,这就是Theme的工作原理,下面会验证。
- 我再自定义一个View比如OtherView extends View,那么还是得在OtherView的构造方法中再次获取这些属性值,所以说Style(样式)是对View有效果。
Activity/Application的Theme(主题)
还是用上面自定义的两个属性,封装一个style,这次由于是用于Activity,那么需要额外的系统自带属性不然Activity不能正常工作,会崩溃
<style name="AppEditStyle" parent="android:Theme.Material.Light">
<item name="circleColor">#343434</item>
<item name="circleSize">40</item>
</style>
在menifest.xml的application节点定义:
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppEditStyle">
<activity android:name=".StyleActivity">
然后在Activity中获取这两个属性:
public class StyleActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_style);
}
@Override
protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
super.onApplyThemeResource(theme, resid, first);
TypedArray ta = theme.obtainStyledAttributes(R.styleable.dml);
int color = ta.getInt(R.styleable.dml_circleColor,-1);
int size = ta.getInt(R.styleable.dml_circleSize,-1);
Log.d("dml","color = " + color + "-------size = " + size);
}
}
看下效果:
05-02 21:38:15.285 19755-19755/com.example.app2 D/dml: color = -13355980-------size = 40
- 同上面的Style一样,在Android系统中我们给Applciation节点设置了Theme,那么在Activity源码中也会相应获取这个主题,然后展示出默认的Activity风格,果然在Activity源码3711行有这个回调方法:
@Override
protected void onApplyThemeResource(Resources.Theme theme, @StyleRes int resid,
boolean first) {
if (mParent == null) {
super.onApplyThemeResource(theme, resid, first);
} else {
try {
theme.setTo(mParent.getTheme());
} catch (Exception e) {
// Empty
}
theme.applyStyle(resid, false);
}
// Get the primary color and update the TaskDescription for this activity
if (theme != null) {
TypedArray a = theme.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0);
a.recycle();
if (colorPrimary != 0) {
ActivityManager.TaskDescription v = new ActivityManager.TaskDescription(null, null,
colorPrimary);
setTaskDescription(v);
}
}
}
下一篇:介绍下Android系统有哪些常见的主题
网友评论