一、构造方法
1.一个参数 Context context,需要在代码中new出来
2.两个参数 Context context, AttributeSet attrs,在布局文件中添加该控件,对应的属性会存放在AttributeSet attrs中。
3.三个参数 Context context, AttributeSet attrs, int defStyleAttr,第三个参数是对应的自定义属性,三个参数的额构造函数不会被自动调用,需要在第二个构造函数中this调用,第三个参数设为0。
二、view的绘制流程
Measure->Layout->Draw
onMeasure(int,int)参数int型,32位,前2位mode,后30位size。
MeasureSpce的mode有三种:EXACTLY, AT_MOST,UNSPECIFIED。
EXACTLY:是明确了控件的大小,或者MATCH_PARENT,父布局(所在的ViewGroup)会将其设置为EXACTLY;
AT_MOST:子布局限制在一个最大之内,一般为WARP_CONTENT,父布局会将其设置为AT_MOST;
UNSPECIFIED:子布局想要多大给多大。
给控件设置了长和宽,onMeasure()测量的是设定的值;设置为WRAP_CONTENT,或者MATCH_PARENT,测量的结果就是MATCH_PARENT的长度,占满父布局。所以当设置为WRAP_CONTENT,需要重写,自己测量。
判断mode,不能直接使用size。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int measuredHeight, measuredWidth;
if (widthMode == MeasureSpec.EXACTLY) {
measuredWidth = widthSize;
} else {
measuredWidth = SIZE; //设置的定值
}
if (heightMode == MeasureSpec.EXACTLY) {
measuredHeight = heightSize;
} else {
measuredHeight = SIZE;
}
setMeasuredDimension(measuredWidth, measuredHeight);
}
onLayout(),只有ViewGroup需要重写该方法,是为了给子控件布局的
三、自定义属性
1.values目录下创建attr.xml
declare-styleable name对应着相应的自定义view
attr:name为自定义属性名称,format为类型
方式1.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NewView">
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
<attr name="text" format="string" />
</declare-styleable>
</resources>
方式2.
<attr name="firstColor" format="color" />
<attr name="secondColor" format="color" />
<attr name="circleWidth" format="dimension" />
<attr name="speed" format="integer" />
<declare-styleable name="CustomProgressBar">
<attr name="firstColor" />
<attr name="secondColor" />
<attr name="circleWidth" />
<attr name="speed" />
</declare-styleable>
2.在布局文件中使用属性
在布局最外层会自动生成命名空间 xmlns:app="http://schemas.android.com/apk/res-auto"
<com.wangpos.test.NewView
app:text="AAAAAAAAA"
app:textColor="@color/colorAccent"
app:textSize="20px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
3.在自定义view中的构造方法中获取自定义属性
获得属性:R.styleable.View名称_属性
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.NewView);
int textColor = a.getColor(R.styleable.NewView_textColor,0XFFFFFFFF);
float textSize = a.getDimension(R.styleable.NewView_textSize, 36);
String text = a.getString(R.styleable.NewView_text);
4.候选值属性,如match_parent,wrap_content
name为名字,value为对应的值
<attr name="position">
<enum name="width" value="300" />
<enum name="height" value="100" />
</attr>
在布局中使用
app:position="height"