Android自定义属性TypedArray学习

概述

​ 有时候android传统的页面布局不足以满足我们的需求,常常需要自己定义view,通常继承View,然后重写构造方法以及onDraw等函数,再具体实现自己定义的复杂view。我们知道在给控件赋属性时,通常使用的是android系统自带的属性,比如 android:layout_height=”wrap_content”,除此之外,我们亦可以自己定义属性,这样在使用的时候我们就可以使用形如 myapp:myTextSize=”20sp” 的方式了

使用
在项目文件res/value下面创建一个attr.xml文件,该文件中包含若干个attr集合

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>  
<resources>
<declare-styleable name="MyView">
<attr name="myTextSize" format="dimension"/>
<attr name="myColor" format="color"/>
</declare-styleable>
</resources>

其中resource是根标签,可以在里面定义若干个declare-styleable<declare-styleable name="MyView">name(最好与自定义view的名字相同) 定义了变量的名称,下面可以再自定义多个属性,针对<attr name="myTextSize" format="dimension"/>来说,其属性的名称为”myTextSize”,format指定了该属性类型为dimension,只能表示字体的大小。

format 可以指定的类型:

  • reference 表示引用,参考某一资源ID

  • string 表示字符串

  • color 表示颜色值

  • dimension 表示尺寸值

  • boolean 表示布尔值

  • integer 表示整型值

  • float 表示浮点值

  • fraction 表示百分数

  • enum 表示枚举值

  • flag 表示位运算

在XML中的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">

<com.ccc.typedarraydemo.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:myTextSize="50sp"
app:myColor="@color/colorAccent"/>

</LinearLayout>

注意看 xmlns:app="http://schemas.android.com/apk/res-auto" , 添加了这句,相当于自定义了一个命名空间,这里为 app ,我们就可以直接使用 app:自定义属性 的格式来引用。

实际上也可以这么写: xmlns:app=”http://schemas.android.com/apk/res/完整的包名”, 在res/后面填写包名即可。但是,在Android Studio2.0后,是不推荐这么写的,所以还是用第一种的命名方法。

在在自定义view的代码中引入自定义属性

context 通过调用 obtainStyledAttributes 方法来获取一个 TypeArray ,然后由该TypeArray来对属性进行设置 obtainStyledAttributes 方法有三个,我们最常用的是有一个参数的 obtainStyledAttributes(int[] attrs),其参数直接 styleable 中获得 TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.MyView);
调用结束后务必调用 recycle() 方法,否则这次的设定会对下次的使用造成影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class MyView extends View {

private Paint paint;

public MyView(Context context) {
super(context);
}


public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
paint = new Paint();

// R.styleable.MyView MyView 就是我们刚才在attrs文件中定义的 declare-styleable 属性的 name
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyView);

// 属性的格式 MyView_myColor 即declare-styleable 属性的 name 和 自定义属性名之间用 -(横杠)连接
int textColor = typedArray.getColor(R.styleable.MyView_myColor, Color.BLUE);
float textSize = typedArray.getDimension(R.styleable.MyView_myTextSize, 35);
paint.setTextSize(textSize);
paint.setColor(textColor);
typedArray.recycle();
}

public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
canvas.drawText("hello world!", 200, 200, paint);
}
}
效果

Demo 地址

https://github.com/Commandercc/DemoEX/blob/master/TypedArrayDemo.zip?raw=true

0%