参考:Android自定义View(二、深入解析自定义属性)
自定义属性:values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomView">
<!--color-->
<attr name="textColor" format="color" />
<!--dimension-->
<attr name="layout_width" format="dimension" />
<!--boolean-->
<attr name="focusable" format="boolean" />
<!--enum-->
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
<!--flag-->
<attr name="gravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
<flag name="right" value="0x05" />
<flag name="center_vertical" value="0x10" />
</attr>
<!--float-->
<attr name="fromAlpha" format="float" />
<!--fraction-->
<attr name="pivotX" format="fraction" />
<!--integer-->
<attr name="framesCount" format="integer" />
<!--reference-->
<attr name="background" format="reference" />
<!--string-->
<attr name="text" format="string" />
<!--系统自带属性-->
<attr name="android:text" />
</declare-styleable>
</resources>
format支持的类型一共有11种:
color
dimension
boolean
enum
flag
float
fraction
integer
reference
string
(1). reference:参考某一资源ID,带有@
属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference" />
</declare-styleable>
属性使用:
<ImageView android:background = "@drawable/图片ID"/>
(2). color:颜色值
属性定义:
<attr name = "textColor" format = "color" />
属性使用:
<TextView android:textColor = "#00FF00" />
(3). boolean:布尔值
属性定义:
<attr name = "focusable" format = "boolean" />
属性使用:
<Button android:focusable = "true"/>
(4). dimension:尺寸值(带单位)
属性定义:
<attr name = "layout_width" format = "dimension" />
属性使用:
<Button android:layout_width = "42dip"/>
(5). float:浮点值
属性定义:
<attr name = "fromAlpha" format = "float" />
属性使用:
<alpha android:fromAlpha = "1.0"/>
(6). integer:整型值
属性定义:
<attr name = "framesCount" format="integer" />
属性使用:
<animated-rotate android:framesCount = "12"/>
(7). string:字符串
属性定义:
<attr name = "text" format = "string" />
属性使用:
<TextView android:text = "我是文本"/>
(8). fraction:百分数
属性定义:
<attr name = "pivotX" format = "fraction" />
属性使用:
<rotate android:pivotX = "200%"/>
(9). enum:枚举值
属性定义:
<declare-styleable name="名称">
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>
属性使用:
<LinearLayout
android:orientation = "vertical">
</LinearLayout>
注意:枚举类型的属性在使用的过程中只能同时使用其中一个,不能 android:orientation = “horizontal|vertical”
(10). flag:位或运算
属性定义:
<declare-styleable name="名称">
<attr name="gravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
<flag name="right" value="0x05" />
<flag name="center_vertical" value="0x10" />
...
</attr>
</declare-styleable>
属性使用:
<TextView android:gravity="bottom|left"/>
注意:位运算类型的属性在使用的过程中可以使用多个值
(11). 混合类型:属性定义时可以指定多种类型值
属性定义:
<declare-styleable name = "名称">
<attr name = "background" format = "reference|color" />
</declare-styleable>
属性使用:
<ImageView android:background = "@drawable/图片ID" />
或者:
<ImageView android:background = "#00FF00" />
(12). 系统属性
我们在自定义View的时候,可以使用系统已经定义的属性。
<declare-styleable name="test">
<attr name="android:text" />
</declare-styleable>
注意,
这里我们是使用已经定义好的属性,不需要去添加format属性(注意声明和使用的区别,差别就是有没有format)。
然后在类中这么获取:
ta.getString(R.styleable.test_android_text);
布局文件中直接使用:
android:text="@string/hello_world"
CustomView
public class CustomView extends View {
private static final String TAG = "CustomView";
/**
* 一个参数的构造方法:直接New一个View的时候调用。
*/
public CustomView(Context context) {
this(context, null);
}
/**
* 两个参数的构造方法:layout布局文件中使用的时候会调用,
* <p>
* 关于它的所有属性(包括自定义属性)都会包含在attrs中传递进来。
*
* @param attrs:AttributeSet可以获得布局文件中定义的所有属性的key和value
*/
public CustomView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 三个参数的构造方法:这个构造方法系统是不调用的,需要我们显示调用并给defStyleAttr传值,
* 多了一个defStyleAttr参数,这是这个view引用style资源的属性参数,
* 也就是我们可以在style中为自定义View定义一个默认的属性样式然后添加进来!
*
* @param defStyleAttr:
* 默认的Style是指它在当前Application或Activity所用的Theme中的默认Style,
* 且只有在明确调用的时候才会生效
*/
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
/**
* 有四个参数的构造函数在API21的时候才添加上
*
* @param context
* @param attrs
* @param defStyleAttr
* @param defStyleRes
*/
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
//自定义属性的获取:
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView);
TypedArray ta2 = context.obtainStyledAttributes(attrs, R.styleable.CustomView,defStyleAttr,defStyleRes);
int color1 = ta.getColor(R.styleable.CustomView_textColor, Color.parseColor("#ff0000"));
int color2 = ta.getColor(R.styleable.CustomView_textColor, Color.BLACK);
float dimension = ta.getDimension(R.styleable.CustomView_layout_width, 30f);
int dimensionPixelOffset = ta.getDimensionPixelOffset(R.styleable.CustomView_layout_width, 30);
int dimensionPixelSize = ta.getDimensionPixelSize(R.styleable.CustomView_layout_width,30);
boolean aBoolean = ta.getBoolean(R.styleable.CustomView_focusable, true);
String string = ta.getString(R.styleable.CustomView_text);
float aFloat = ta.getFloat(R.styleable.CustomView_fromAlpha,0.5f);
int integer = ta.getInteger(R.styleable.CustomView_framesCount, 1);
float fraction = ta.getFraction(R.styleable.CustomView_pivotX, 120, 240, 0.5f);
ta.recycle();
}
}
TypedArray与AttributeSet的区别:
相同点:
获得布局文件中定义的所有属性的key和value
不同点:
TypedArray:直接获取值,用来简化我们的工作的。
AttributeSet:引用类型, 先获取id,再解析id
我们在View的构造方法中,
可以通过AttributeSet去获得自定义属性的值,但是比较麻烦,而TypedArray可以很方便的便于我们去获取。
参考:
getDimension,getDimensionPixelOffset和getDimensionPixelSize的区别
getDimension,getDimensionPixelOffset,getDimensionPixelSize
getDimension,getDimensionPixelOffset和getDimensionPixelSize的区别:
共同点:
都会根据density将其他单位dp,sp的数值转为px,px单位的保持不变。
不同点:
getDimension返回的是单位是px的float,不对值进行任何处理,
getDimensionPixelSize是返回int (px单位),小数部分进行四舍五入,
getDimensionPixelOffset是返回int(px单位),将结果直接截断小数位,抹去小数部分
控件里面从xml中获取的dimens的大小都是通过getDimensionPixelSize(四舍五入)来转换成px为单位的。