先从是什么开始
在日常开发中,我们会经常接触到Attr、Style、Theme这三个概念,但许多小伙伴一直对它们一知半解,在深入了解之前,这里先给出它们三者的基本定义。
- Attr:属性(Attribute),用于指定UI的某种风格样式,比如android:layout_width就是一种Attr;
- Style:风格,一系列Attr的集合,用于为UI指定一个“复合风格样式”;
- Theme:主题,与Style的作用一样,区别于Style的作用范围是View,而Theme的作用范围是Activity或Application。
接下来我们来逐一详细介绍Attr、Style与Theme。
Attr
Framework中的Attr
我们在平时的开发中,更多的是使用Attr,只有在自定义View时才会定义Attr。Attr的定义很简单,我们拿平常经常使用的android:layout_xxx属性来举例,看看Android Framework中是如何定义Attr的。(取自
从以上代码中我们可以看到,layout_xxx属性的取值范围为三个枚举值,其中使用fill_parent和match_parent是等价的,因为他们的value相同,之所以保留fill_parent,是为了兼容老版本。format表示了Attr的类型,可取的值有以下类型:
- color:颜色值,如#000000
- reference:引用某一资源ID。如@drawable/xxx
- boolean:布尔值,true或false
- dimension:尺寸值,可以为wrap_content、match_parent或是具体大小(xx dp)
- float:浮点型
- fraction:百分数
- integer:整型
- string:字符串类型
- enum:枚举类型,各个取值互斥
- flag:标记位,各个取值可用“|”连接
接下来,我们来看下LinearLayout的showDividers属性的定义:
我们可以看到,它的取值有四种。那么问题来了,enum与flag标签的区别是什么呢?正如我们上面所提到的,这两者的区别在于flag的几个取值不互斥,而enum的几个取值是互斥的。
自定义Attr
自定义Attr十分简单,只需要在res/values目录下新建一个attrs.xml,然后仿照Framework中的定义即可,这里我们定义一个名为MyStyle的属性组:
使用Attr
我们在布局文件中这样使用自定义Attr:
使用自定义Attr时我们要自定义一个命名空间,上例中我们自定义的命名空间为myview,com.example.customview为我们的自定义View类所在包。
获取自定义Attr
一种常见的在自定义View类中获取Attr的代码是这样的:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyStyle);
String name = ta.getString(R.styleable.MyStyle_myName, "absfree");
. . .
}
而上面代码中的obtainStyledAttributes方法最终调用的是以下重载版本的方法:
public final TypedArray obtainStyledAttributes (AttributeSet set, int[] attrs,
int defStyleAttr, int defStyleRes)
我们来解释以下这个方法四个参数的含义:
- set:属性集,会传入到自定义View的构造器中,它保存了布局文件中为View指定的所有属性
- attrs:想要获取的属性
- defStyleAttr:表示一个指向Style的类型为reference的Attr
- defStyleRes:表示Style的资源ID
后两个参数都用于指定默认Style,当从attrs中找不到我们想要获取的属性时,就会使用默认Style,其中defStyleAttr的优先级高于defStyleRes。
Style
自定义Style
在res/values/styles.xml的
如此一来,我们便定义了一个名为MyStyle的Style,接下来我们看看如何使用它。
使用自定义Style
使用自定义Style与使用自定义Attr相仿:
如此一来,在MyView类中,我们便可以通过Theme的obtainStyledAttributes获取到自定义Style的值。比如以下代码可以后去到MyStyle中的myName的值。
final Resources.Theme theme = context.getTheme();
TypedArray ta = theme.obtainStyledAttributes(attrs, R.styleable.MyStyle,
defStyleAttr, defStyleRes);
String name = ta.getString(R.styleable.MyStyle_myName);
ta.recycle();
这里的obtainStyledAttributes方法即为我们上面获取Attr时使用的方法。
Theme
自定义Theme
自定义Theme的方法与自定义Style相同,也使用
Style的优先级要高于Theme,如此一来我们可以先定义整个应用的整体风格样式,然后可以根据需要对局部风格样式做出个性化修改。
获取Theme中的Attr
在xml文件中获取Theme中Attr的语法如下:
?[:][/]
若是本应用中的Attr,则可以省去
比如,我们向把TextView的text指定为MyStyle中的myName,只需按如下设置:
参考资料
- Android自定义View属性的相关细节
- 深入理解Android中的自定义属性
- Attr、Style和Theme详解
**长按或扫描二维码关注我们,让您利用每天等地铁的时间就能学会怎样写出优质app。 **