一、View的测量
1.自定义View前首先要对View进行测量,即告诉系统应该画一个多大的View,这个过程在onMeasure()中进行
Android通过MeasureSpec类来帮助测量View。
2.MeasureSpec它有三种测量模式
EXACTLY:精确模式,当layout_height/layout_width属性为具体值或指定为match_parent时,为精确模式
AT_MOST: 最大值模式,当layout_height/layout_width属性为wrap_content时,控件大小随子控件变化,只要不超过父部件允许的尺寸即可
UNSPECIFIED:不指定其大小测量模式,View大小随意,通常自定义View下才使用
View的onMeasure()方法默认只支持EXACTLY模式,如果要让自定义View支持wrap_content就必须重写onMeasure()方法
二、View的绘制
View测量好之后,就要重写onDraw()方法来绘图
onDraw()方法中有一个参数canvas,通过这个对象就可以绘图了,而在其他地方需要创建一个Canvas对象
Canvas canvas = new Canvas(bitmap);
传进去的canvas与通过这个bitmap创建的Canvas画布是联系的一起的,此过程为装载画布。
这个bitmap用来存储绘制在canvas上的像素信息,如Canvas.drawXXX方法绘制的图会发生在这个bitmap上。
三、对现有控件扩展
通过继承系统组件,我们可以对现有控件扩展。
先介绍一下几个常用的回调方法
onFinishInflate() //从XML加载组件后调用
onSizeChanged //组件大小改变时回调
onMeasure //回调该方法来进行测量
onLayout //回调该方法来确定显示的位置
onTouchEvent //监听触摸事件的回调
onDraw //组件绘制时调用
自定义控件有三种方式
1.对现有控件进行拓展
2.通过组合来实现新的控件
3.重写View来实现全新的控件
四、举例
我们继承一个Button,在其四角画四个实心圆,在其中心画三个空心圆,并将背景改为粉红色
1.新建java类myButton,继承Button
记住要导入其构造方法
public MyButton(Context context) {
super(context);
initView();
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
2.声明画笔
因为onDraw方法中有canvas,所以只需要声明画笔即可
private Paint paint1,paint2;
设置画笔属性
private void initView() {
paint1 = new Paint();
paint1.setColor(getResources().getColor(android.R.color.holo_orange_light));
paint1.setStyle(Paint.Style.FILL); //实心
paint2 = new Paint();
paint2.setColor(getResources().getColor(android.R.color.holo_blue_bright));
paint2.setStyle(Paint.Style.STROKE); //空心
}
3.重写onDraw方法
/*
* 程序调用super.onDraw(canvas);实现原生控件的功能,我们可以在其前后设计自己的控件*/
@Override
protected void onDraw(Canvas canvas) {
//调用父类方法前,实现自己的逻辑,
//四个实心圆
canvas.drawCircle(0,0,30,paint1);
canvas.drawCircle(0,getHeight(),30,paint1);
canvas.drawCircle(getWidth(),0,30,paint1);
canvas.drawCircle(getWidth(),getHeight(),30,paint1);
//三个空心圆
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/8,paint2);
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/6,paint2);
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/4,paint2);
//设置背景
setBackground(getResources().getDrawable(R.color.colorAccent));
canvas.save(); //保存画布
super.onDraw(canvas); //父类方法
//调用父类方法后,实现自己的逻辑
canvas.restore(); //合并图像
}
5.引用
<myView.MyButton
android:id="@+id/main_my_btn_expendView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ExpendView1"
android:textAllCaps="false"
android:layout_margin="10dp" />
效果
6.之后和正常的按钮一样实例化设置点击事件一样一样的