一、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.之后和正常的按钮一样实例化设置点击事件一样一样的