xml文件中的theme和style属性的区别与联系
注意:这里讲的theme和style是xml中某个标签(如application标签)中的属性,而不是标签,后面要讲的style标签其实是属性值(即style属性的值)。总之,前者是属性后者(即标签)是属性值。
theme属性和style属性
<application android:theme="@style/CustomTheme">
<TextView android:style="@style/myStyle" />
style标签
<style/>
区别
-
作用范围不同
对于Android开发者来说Theme主要是针对窗体及Activity级别的,通常改变的是窗体的样式;而Style主要是针对窗体及Activity中具体成员元素级别的,通常改变的是控件的样式。简单粗暴理解就是Theme作用于所有(若在Theme 中单独为background 这一属性赋值,则对所有View的background都起作用,ViewGroup和它的子成员的背景会重叠)支持属性的子成员,Style作用于指定的成员。 -
赋值方式不同
theme的赋值方式:
系统为theme这一属性提供了多个属性值(都含有Theme),比如Theme.Light 。
使用系统自带主题赋值的方式:@android:style/
使用自定义主题赋值的方式:@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>
style属性的赋值方式:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:style="@style/myStyle" />
联系
实际上,theme实质上是style,因为theme和style属性的值都通过style 标签定义得到的。
参考:Android开发之Theme、Style探索及源码浅析
style、declare-styleable、attr这三个标签的区别与联系
注意:这三个标签分别对应R类中的R.style、R.styleable、R.attr这三个内部类。
区别
- attr
attr标签用于定义属性。attr不依赖于declare-styleable,declare-styleable只是为了方便attr的使用。
我们自己定义属性完全可以不放到declare-styleable里面,比如直接在resources文件中定义一些属性:
<attr name="custom_attr1" format="string" />
<attr name="custom_attr2" format="string" />
- declare-styleable
declare-styleable标签用于把相关的属性组织起来,有一个分组的概念。
作用:
1、属性的使用范围更加明确(比如declare-styleable标签定义的TextViewStyle,开发者通过字面意思可知其中的属性用于更改TextView样式的,因此当我们想要知道Theme具体有哪些属性可以有效使用时,可以查阅API的R.styleable进行选择,也可查SDK中android自带的attrs.xml中的declare-styleable标签)。
2、便于在创建View时获取xml或主题等中设置的属性值
<declare-styleable name="custom_attrs">
<attr name="custom_attr1" format="string" />
<attr name="custom_attr2" format="string" />
</declare-styleable>
创建View时获取属性值的方式:
TypedArray typedArray = context.obtainStyledAttributes(set,R.styleable.custom_attrs);
若是定义的属性不放到declare-styleable标签中,则在创建View时获取属性值的方式:
int[] v = {R.attr.custom_attr1, R.attr.custom_attr2};
TypedArray typedArray = context.obtainStyledAttributes(set,v);
- style
为一组attr属性赋值。
联系
自定义View 时,获取属性值是通过obtainStyledAttributes 函数。例子:
//自定义View
TypedArray typedArray = context.obtainStyledAttributes(set,R.styleable.custom_attrs);
//ImageView
public ImageView(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ImageView, 0, 0);
Drawable src = ta.getDrawable(R.styleable.ImageView_src);
setImageDrawable(src);
ta.recycle();
}
函数的声明:
- obtainAttributes(AttributeSet set, int[] attrs)
从layout设置的属性集中获取attrs中的属性,若还有属性的值未获取到还会从主题中获取。 - obtainStyledAttributes(int[] attrs)
从主题中获取attrs中的属性。 - obtainStyledAttributes(int resId,int[] attrs)
从资源文件定义的style中读取属性,若还有属性的值未获取到还会从主题中获取。 - obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
数据来源:set、defStyleAttr、NULL(即主题中直接指定的属性值,也就是主题中单一的某个attr 属性的值)、defStyleRes。
参数介绍:
- AttributeSet set(数据源):即XML中的属性,表示从layout文件中直接为这个View添加的属性的集合(一种是直接使用android:layout_width=“wrap_content"这种直接指定,还有一种是通过style=”@style/somestyle"指定。)
- int[] attrs(目标数据的id):即想要哪个属性的值。每个元素代表一个属性在R.attr 中的id。
- int defStyleAttr(数据源):可配置样式。主题中配置的样式。
例子:
<resources>
<style name="Theme">
<!-- ...snip... -->
<item name="textViewStyle">@style/Widget.TextView</item>
<!-- ...etc... -->
</style>
</resource>
textViewStyle 就是可配置样式,该样式只有在 obtainStyledAttributes 函数中为形参 defStyleAttr 设置了 “com.android.internal.R.attr.textViewStyle” 时, @style/Widget.TextView 中设置的属性值才会起作用。
- int defStyleRes(数据源):defStyleRes就要比defStyleAttr简单多了。它只是一个style资源(@style/Widget.TextView)。不需要间接的通过theme。只有当 defStyleAttr 没有定义时(设置为0,或者没有在主题中设置),defStyleRes 才有效。
,如果一个属性在多个地方都被定义了,那么以哪个为准?
优先级如下:
set 中直接指定的值 > set 中的style 资源(如:style=@style/blah)> defStyleAttr > defStyleRes > NULL(主题中直接指定的值,不包括可配置样式)
注:无论用哪个obtainAttributes 函数,当找不到属性值时,会从主题中直接指定值的属性找。 主题中的可配置样式必须在obtainStyledAttributes 函数中传入该样式在R类中的id 即defStyleAttr 才会起作用。
参考:深入理解Android 自定义attr Style styleable以及其应用
修改主题中的可配置样式
自定义主题时,继承了android 提供的主题后,修改单个属性一般是针对window 的属性,因为只作用于window,其他属性一般不要单独设置。