自定义属性相关的理解
简单的记录下理解收获。。。。
知识点
通过知识点也可以知道本节主要围绕TypedArray来理解属性获取相关知识点。
自定义属性过程理解图
自定义view中获取自定义属性
1、TypedArray对象获取
(1)常用方法
obtainAttributes(AttributeSet set, int[] attrs)
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
原因:在自定义view时必须重写几个构造方法,这时AttributeSet 这个参数已经提供,直接传参即可。
1、其实AttributeSet 就是你使用的view的属性和属性值的集合。
2、attrs其实是属性资源id集合(一般我们通过styleable方式传参)
2、AttributeSet 的理解
(1)理解
通过AttributeSet可以获得布局文件中定义的所有属性的key和value.
(2)思考
通过AttributeSet 就可以获得?那还要TypedArray干嘛?其实AttributeSet 会有些弊端,比如textview的text属性你使用了引用字符串的方式,这时使用AttributeSet来获取值时要注意啦。而使用安卓提供的TypedArray可以轻易获取。
3、obtainStyledAttributes四个重载的理解
(1)方法
//1
public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs)
//2
public final TypedArray obtainStyledAttributes(@StyleRes int resid, @StyleableRes int[] attrs)
//3、自定义view中常用
public final TypedArray obtainStyledAttributes(AttributeSet set, @StyleableRes int[] attrs)
//4
public final TypedArray obtainStyledAttributes(
AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr,@StyleRes int defStyleRes)
1、需要一个id数组,id是StyleableRes 类型的
3、需要AttributeSet 和id数组,id是StyleableRes 类型的。
ps:@StyleableRes到底是啥,其实你获取TypedArray (context.obtainStyledAttributes(attrs, R.styleable.SettingView))传递的第二个参数底层就生成了id数组,系统生成的。
(2)方法深入
发现这四个方法底层都是调用Context类的getTheme().obtainStyledAttributes方法。再深入发现又调用了Resources类的obtainStyledAttributes方法,最终是Resources类的实现类ResourcesImpl的obtainStyledAttributes进行处理
//ResourcesImpl.java
TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
AttributeSet set,
@StyleableRes int[] attrs,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes) {
synchronized (mKey) {
final int len = attrs.length;
final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
// XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse
// out the attributes from the XML file (applying type information
// contained in the resources and such).
final XmlBlock.Parser parser = (XmlBlock.Parser) set;
mAssets.applyStyle(mTheme, defStyleAttr, defStyleRes, parser, attrs,
array.mDataAddress, array.mIndicesAddress);
array.mTheme = wrapper;
array.mXml = parser;
return array;
}
}
自定义view中获取自定义属性
这个第一次是在RecyclerView提供的默认分割线实现类中看到
public class DividerItemDecoration extends ItemDecoration {
...
...
private static final int[] ATTRS = new int[]{16843284}; // id 数组,16843284为某资源id值
...
...
public DividerItemDecoration(Context context, int orientation) {
TypedArray a = context.obtainStyledAttributes(ATTRS); // 获取TypedArray对象
this.mDivider = a.getDrawable(0);
if (this.mDivider == null) {
Log.w("DividerItem", "@android:attr/listDivider was not set in the theme used for this DividerItemDecoration. Please set that attribute all call setDrawable()");
}
a.recycle();
this.setOrientation(orientation);
}
(1)常用方法
初次碰到时会发现,不是自定义view中,AttributeSet肯定用不了了,只能使用TypedArray获取啦。
//1、在Context的主题中检索样式化属性信息
public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs)
//2、在Context的主题中检索样式化属性信息
public final TypedArray obtainStyledAttributes(@StyleRes int resid, @StyleableRes int[] attrs)
一般使用第一个,传资源id数组即可。
获取自定义属性值的几种方式
常见三种获取方式:
- attrs.getAttributeXXXValue(命名空间,自定义属性名字)
- for (int i=0;i<attrs.getAttributeCount();i++) 从属性集合中获取
- 使用TypedArray(推荐)
end
建议必读:
Android 深入理解Android中的自定义属性