概述
还记得我们自定义 View 的场景吗?写完 extends View
后,快捷键一挥,自动生成了几个构造函数:
1 | public TestTextView(Context context) { |
对于重载的这几个构造方法,他们的参数都是不一样的,不知道大家有没有思考过这些参数的作用呢?本文就这些参数做一个简单介绍。
AttributeSet
attrs
参数中保存的是我们为该View设置的所有的属性,比如我们在xml布局文件中配置如下:
1 | <com.example.heqiang.testsomething.attr.TestTextView |
那么我们在构造方法中打印 attrs 的信息:
1 | public TestTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { |
得到的结果为:
1 | attrName = layout_width , attrVal = -2 |
也就是我们在布局文件中配置的三个属性。
defStyleAttr
先来看看源码文档中对 defStyleAttr 的解释:
1 | * @param defStyleAttr An attribute in the current theme that contains a |
defStyleAttr 是定义在 theme 中的一个引用,这个引用指向一个style资源,而这个style资源包含了一些属性的默认值,如果我们在布局中没有为 View 设置的一些属性(attrs 中没有的属性),就会在 defStyleAttr 查找默认值。如果设置为 0 就不会去查找默认属性。
我们先在 attrs.xml 中声明一个自定义的属性:
1 | <declare-styleable name="myViewStyle"> |
然后在 styles.xml 中声明一个 View 的默认样式,然后把这个样式在 Activity 的主题中为 myCutsomViewStyle
赋值:
1 | <style name="customText2"> |
然后在构造方法中为 defStyleAttr 设置:
1 | public TestTextView(Context context, @Nullable AttributeSet attrs) { |
defStyleRes
先来看看源码文档中对 defStyleRes 的解释:
1 | * @param defStyleRes A resource identifier of a style resource that |
defStyleRes 也是为 View 配置的一些默认的属性值,但是仅仅在 defStyleAttr 为 0 或者在 主题中找不到设置的 defStyleAttr 时,defStyleRes 才会生效。如果设置为 0,那么就不会在查找 defStyleRes 配置的默认值。
首先在 styles.xml 中设置一个样式:
1 | <style name="customText"> |
然后在构造方法中设置:
1 | public TestTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { |
优先级
在 Android – Attr、Style和Theme 一文中介绍了属性使用的优先级,那么现在我们再加上一个:布局文件中设置的值 > View 构造方法中的 defStyleAttr(不设置 defStyleAttr 时是defStyleRes) > View style > Activity theme > Application theme。