一、四个构造函数
CustomView(Context context)
- 源码注释
Simple constructor to use when creating a view from code. 只是用代码创建view时调用 - 参数context,不做过多解释
CustomView(Context context, AttributeSet attrs)
- 源码注释
Constructor that is called when inflating a view from XML. This is called when a view is being constructed from an XML file, supplying attributes that were specified in the XML file. This version uses a default style of 0, so the only attribute values applied are those in the Context’s Theme and the given AttributeSet. 用xml inflate生成view时调用,可以在xml中设置属性,在此构造函数中读取出来。 参数(Context context, AttributeSet attrs)
AttributeSet :A collection of attributes, as found associated with a tag in an XML document.在xml文件的标签中作为属性的集合。
解释比较笼统,看一段代码就知道了布局文件: <com.example.test.CustomView android:layout_width="100dp" android:layout_height="200dp" app:testAttr1="520" app:testAttr2="helloworld" /> java代码: public CustomView(Context context, AttributeSet attrs) { super(context, attrs); int count = attrs.getAttributeCount(); for (int i = 0; i < count; i++) { String attrName = attrs.getAttributeName(i); String attrVal = attrs.getAttributeValue(i); Log.e(TAG, "attrName = " + attrName + " , attrVal = " + attrVal); }} 结果: attrName = layout_width, attrVal = 100.0dip attrName = layout_height, attrVal = 200.0dip attrName = app:testAttr2, attrVal = helloworld attrName = app:testAttr1, attrVal = 520
简单理解就是view属性的一个map而已。其中map里key为属性名,value为属性值。但是,相信有经验的开发者写自定义控件的时候,都不会这么取属性值,小伙伴应该都是这么干的
自定义属性的声明文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="sttyleName">
<attr name="attrName" format="string" />
</declare-styleable>
</resources>
java代码:
public class CustomView extends View {
public CustomView(Context context, AttributeSetattrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.sttyleName);
String text = ta.getString(R.styleable.attrName);
ta.recycle();
}
}
咋一看,是绕了一圈,通过TypedArray去获取的view属性,可是,这个TypedArray是啥子东东,平时只是用了,估计也没多想。事实上,这样不但没有绕圈,反而是走了一个捷径。下面来做分析:
如果xlm的自定属性是这样的(属性值不是具体值,而是“reference”)
布局文件:
<com.example.test.CustomView
android:layout_width="@dimen/dp100"
android:layout_height="@dimen/dp200"
app:testAttr1="520"
app:testAttr2="helloworld" />
再用上面那种遍历属性的方法得到结果就出乎意料了:
结果:
attrName = layout_width, attrVal = @2131165234
attrName = layout_height, attrVal = @2131165235
attrName = app:testAttr1, attrVal = 520
attrName = app:testAttr2, attrVal = helloworld
“@2131165234”、“@2131165235”傻眼了吧,还是得通过TypedArray来获得属性。但是有没有发现一个问题,在自定义声明属性中,我们多套了一层“ ”标签,其实可以直接写属性。这样来:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="attrName" format="string" />
</resources>
但是,但是,但是(重要的事情说三遍),我们读取属性的java代码得这样写了:
public class CustomView extends View {
private static final int[] mAttr =
{android.R.attr.attrName};
private static final int ATTR_ANDROID_TEXT = 0;
private static final int ATTR_TESTATTR = 1;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, mAttr);
String text = ta.getString(ATTR_ANDROID_TEXT);
ta.recycle();
}
}
可以做个对比,是不是为了少写了个标签,多写了好多的代码,其实就是手动的把数组建出来了。这点也可以从R文件看出来:
带标生成文件
public static final class styleable { public static final int[] sttyleName = { 0x7f010000, 0x7f010001 }; public static final int Customize_attr1 = 1; public static final int Customize_attr2= 2; }
不带标生成文件
public static final class styleable { public static final int Customize_attr1 = 1; public static final int Customize_attr2= 2; }
意思就是使用标签,系统会自动创建一个数组。
CustomView(Context context, AttributeSet attrs, int defStyleAttr)
- 源码注释:
Perform inflation from XML and apply a class-specific base style from a theme attribute. This constructor of View allows subclasses to use their own base style when they are inflating. For example, a Button class’s constructor would call this version of the super class constructor and supplyR.attr.buttonStyle
for defStyleAttr; this allows the theme’s button style to modify all of the base view attributes (in particular its background) as well as the Button class’s attributes.
不会被系统主动调用,只能通过其他构造函数来显示调用。defStyleAttr就是上文在attr里定义在Theme里使用的CustomViewStyle
CustomView (Context context, AttributeSet attrs, int defStyleAttr, int defStyleResr)
- 源码注释:
Perform inflation from XML and apply a class-specific base style from a theme attribute or style resource. This constructor of View allows subclasses to use their own base style when they are inflating.
该方法在SDK版本高于21时才出现