View 构造方法中第三个参数 defStyleAttr

今天使用一个自定义控件继承自 AppCompatButton, 字体不是居中的, 最后排查发现是构造方法的问题;

对比 AppCompatButton 的源码发现是 defStyleAttr 参数的问题

对 defStyleAttr 参数的解释:

The resource identifier of an attribute in the current theme whose value is the the resource id of a style. The specified style’s attribute values serve as default values for the button. Set this parameter to 0 to avoid use of default values.

当前 Theme 主题中的一个资源标识符, 其值引向一个 style 样式; 这个样式里有一些 button 的属性默认值; 如果设置为0就不使用默认值;


从源码中查看 AppCompatButton 的 R.attr.buttonStyle

attrs.xml 中定义的 buttonStyle:

/frameworks/base/core/res/res/values/attrs.xml

Theme 和 style 中定义的内容

所以第三个参数为 0 时, android:gravity 的默认值未设置, 导致文本位于左上角;

从上面的例子中可以看出,通过 下列方法可以写自己的 style 加到主题中

1: 在 attrs.xml 文件中添加属性 name

2: Theme 中将步骤一的name, 对应到一个样式 style

3: 在自定义 view 的 defStyleAttr 处使用这个样式

继承 View 的自定义控件不需要处理第三个构造参数

可以看到继承 View 的子类不需要特殊的 style, 所以一开始自定义 View 从继承 View 开始练习, 很容易忽视对第三个参数的处理;


结论: Android 自定义 View, 如果继承自非 View 的控件, 需要看下父控件的源码, 考虑 defStyleAttr 的取值;

解析属性的优先级: xml > style > defStyleAttr > defStyleRes(defStyleAttr为0时的默认 style) > theme

补充:

  • 第二个参数 attrs 是 xml 指定的属性
  • 可以借助下面的方法获取完整的属性值

    TypedArray a = theme.obtainStyledAttributes(attrs,defStyleAttr, defStyleAttr, defStyleRes);
0 Comments
Leave a Reply