1 自定义属性值
自定义view的起步是自定义属性,并且正确的读取属性。
在res/values/attrs.xml的文件中创建属性:
<declare-styleable name="ViewDemoAttr35">
<attr name="string35" format="string"/>
<attr name="boolean35" format="boolean"/>
<attr name="color35" format="color"/>
<attr name="integer35" format="integer"/>
<attr name="enum35" format="enum">
<enum name="enum0" value="0" />
<enum name="enum1" value="1" />
<enum name="enum2" value="2" />
</attr>
<attr name="dimension35" format="dimension"/>
<attr name="float35" format="float"/>
<attr name="reference351" format="reference"/>
<attr name="reference352" format="reference"/>
<attr name="reference353" format="reference"/>
<attr name="reference354" format="reference"/>
<attr name="fraction35" format="fraction"/>
<attr name="bg351" format="color|reference"/>
<attr name="bg352" format="color|reference"/>
<attr name="flag35" >
<flag name="flag1" value="1"/>
<flag name="flag2" value="2"/>
</attr>
</declare-styleable>
或者:
<!--属性声明-->
<attr name="demo1" format="string"/>
<!--属性使用-->
<declare-styleable name="MyTextView">
<attr name="demo1"/>
</declare-styleable>
两种方式略有不同,第一种方式定义的属性只能在内部使用,第二种方式定义的属性作为公共属性,其他自定view也可以使用。
自定义属性需要name和format,name是属性的名字,format是属性的格式:
Android支持的属性格式包括:
- string 属性取值为string,或者指向R.string.id 的一个资源
- color 属性取值为颜色,类似#cdcdcd,或者指向R.color.id
- boolean 属性取值为true或者false
- dimension 属性取值为尺寸类型,例如px,sp,dp也可以指向一个R.dimen.id
- enum 属性指向具体的枚举值
- flag 属性指向一个flag类型,位运算,类似enum,
- float 属性指向一个float
- fraction 属性指向一个百分数,只能是xx%样式的数据
- integer 属性指向一个int值
- reference 属性指向一个引用id,类似R.drawable.id
注意:
attr节点有两种子节点,enum和flag,enum和flag不能混合使用。
enum可在format声明,也可以不声明,当attr节点内有enum节点时,attr可以赋值为enum。
flag不可在format声明,当attr节点内有flag节点时,attr可以赋值为flag。
enum子节点的声明,value的值只能是int类型,且只能有一个值。
flag的声明,value也只能是int,但是可以利用|设置多个值。
还可以定义为 color|reference 一般用于颜色 @color/。
2 读取属性
自定义View需要实现三个构造函数(最好),属性就存储在attrs中,利用Context的obtainStyledAttributes方法得到TypedArray 对象进行属性获取,最后需要调用TypedArray 的recycle方法进行回收。
public ViewDemo35(Context context) {
this(context,null);
}
public ViewDemo35(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public ViewDemo35(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
handleCustomAttrs(context,attrs);
init();
}
private void handleCustomAttrs(Context context,AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ViewDemoAttr35);
String str = typedArray.getString(R.styleable.ViewDemoAttr35_string35);
boolean boo = typedArray.getBoolean(R.styleable.ViewDemoAttr35_boolean35, false);
int color1 = typedArray.getColor(R.styleable.ViewDemoAttr35_color35, Color.BLUE);
int intege = typedArray.getInteger(R.styleable.ViewDemoAttr35_integer35, 10);
int enum1 = typedArray.getInt(R.styleable.ViewDemoAttr35_enum35, 1);
int size1 = typedArray.getDimensionPixelSize(R.styleable.ViewDemoAttr35_dimension35, 22);
float float1 = typedArray.getFloat(R.styleable.ViewDemoAttr35_float35, 22);
int resid1 = typedArray.getResourceId(R.styleable.ViewDemoAttr35_reference351, R.drawable.close_icon);
int resid2 = typedArray.getResourceId(R.styleable.ViewDemoAttr35_reference352, R.color.black);
Drawable drawable1 = typedArray.getDrawable(R.styleable.ViewDemoAttr35_reference353);
int resid3 = typedArray.getResourceId(R.styleable.ViewDemoAttr35_reference354, R.drawable.compositedst1);
float fraction = typedArray.getFraction(R.styleable.ViewDemoAttr35_fraction35,1,1,0.1f);
int color2 = typedArray.getColor(R.styleable.ViewDemoAttr35_bg351,R.drawable.gradientdemo);
int color3 = typedArray.getColor(R.styleable.ViewDemoAttr35_bg352,R.drawable.background_tab);
int int4 = typedArray.getInt(R.styleable.ViewDemoAttr35_flag35, 1);
typedArray.recycle();
}
}
typeArray的getXXX函数的第一个参数组成styleable的name+_+属性name,例如.styleable.ViewDemoAttr35_fraction35,ViewDemoAttr35是styleable的名字,fraction35是属性名。
3如何使用
AS 下,布局文件根目录工具推荐的方法,只写一个命名空间
xmlns:app="http://schemas.android.com/apk/res-auto,就可以包含所有的自定义属性,利用app:的前缀就可以使用所有的自定义属性了。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Main15Activity2">
<com.ldx.canvasdrawdemo.LinearLayoutDemo
android:id="@+id/view_group_demo"
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical">
<TextView
android:id="@+id/demo_tv1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="sjldjflsjfljs"/>
</com.ldx.canvasdrawdemo.LinearLayoutDemo>
<com.ldx.canvasdrawdemo.ViewDemo35
android:layout_width="match_parent"
android:layout_height="100dp"
app:string35="string35"
app:boolean35="true"
app:color35="#cdcdcd"
app:integer35="22"
app:enum35="enum0"
app:dimension35="25dp"
app:float35="22"
app:reference351 = "@drawable/ic_launcher_background"
app:reference352 = "@drawable/shape_deep_blue"
app:reference353 = "@drawable/have_icon"
app:reference354 = "@drawable/image_home_game_nor2"
app:fraction35 = "20%"
app:bg351 = "@color/colorPrimary"
app:bg352 = "@color/black"
app:flag35 = "flag1" />
</android.support.constraint.ConstraintLayout>