爱哥的自定义View其实很简单
鸿洋大神的Android自定义view
Android群英传(徐宜生)
自定义View这件事,确实如鸿洋大神所说,对于新手来说是一件比较恐怖的事情。比如在下这只小菜鸟,一直想好好学习自定义View,却又总是半途而废。这一次,一定坚持掌握自定义View技巧。
那么让我们进入正题:
在学习自定义View之前,先让我们了解一下Android的控件架构
在Android中,控件大致被分为两类:VIew和ViewGroup。
ViewGroup作为父控件,可以包含多个View,并对其进行管理。通过ViewGroup,整个界面上就形成了一个控件树,上层控件负责对下层控件的测量和绘制。并且传递交互事件。通常,我们用到的findviewById就是通过遍历控件树来寻找对应的元素。
好的,简单的了解一下,让我们进入正题,究竟如何实现自定义view呢。
在Android中,自定义View必定是继承View或者是VIew的子控件,如:Button、TextView等等。
首先我们继承自VIew。
public class MyCircle extends View {
}
IDE主动提示我们要声明构造方法;
public CustomCircle(Context context) {
this(context, null);
}
//此构造方法解析Android自带的属性
public CustomCircle(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
//此构造方法解析自定义的属性
public CustomCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
我们重写了三个构造方法,将前两个方法中的super该为this,如果不改的话,会在onDraw中使用画笔的时候报空指针异常,因为根本走不到第三个构造方法。
接下来我们先重写onDraw方法,
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
当我们要画一些什么的时候,我们就要在这个方法中进行操作,在现实生活中,我们如果想要画画的话,首先需要的就是画笔和画板。当然,Android也给我们提供了Paint和Canvas,一个是画笔,当然另一个就是画布啦。我们可以看到,在onDraw方法中,画布Canvas是作为参数传递进了这个方法中,也就是说这个画布是Android为我们准备好的,我们不用去管就是了。
好了,现在有了画布,我们还需要一个画笔Paint,
在爱哥的博客中我们知道,因为Android不建议我们在draw和layout的过程中去初始化话画笔,因为这两个过程可能是需要频繁进行重复操作的过程,我们知道new是需要分配内存空间的,如果我们如此频繁的去进行new操作,内存会不会爆呢?这个我们并不知道,但浪费内存这个确实可以肯定的。所以Android不建议我们在这两个过程中初始化画笔。
那我们就在构造方法中实例化对象
public CustomCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initPaint();
}
private void initPaint() {
//初始化画笔并打开抗锯齿模式
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
/*
* 设置画笔样式为描边并填充
*
* 画笔样式分三种:
* 1.Paint.Style.STROKE:描边(圆环嘛)
* 2.Paint.Style.FILL_AND_STROKE:描边并填充
* 3.Paint.Style.FILL:填充
*/
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
// 设置画笔颜色为黄色
mPaint.setColor(Color.YELLOW);
/*
* 设置描边的粗细,单位:像素px
* 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
*/
// mPaint.setStrokeWidth(10);
}
现实中的画笔,我们可以去挑选颜色、类型等等等等各种属性,当然在Android我们也可以去设置paint的各种属性,现实中有的,Android有,现实中没有的,Android还有。
当然,Paint集成了画的属性,那么Canvas就定义了我们所要画的东西。
@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas);
/*
* 画一个圆,
* 第一个参数为水平方向的中心坐标
* 第二个参数为垂直方向的中心坐标
* 第三个参数为圆的半径
* 第四个参数为我们的画笔
* */
canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0] / 2, 300, radiu, mPaint); }
现在我们的圆是确确实实的画出来了
按照爱哥的想法,我们现在要实现让圆从小到大不断的变化。
就这样我们让我们的class实现了Runnable方法,
@Override
public void run() {
/*
* 确保线程不断执行不断刷新界面
*/
while (true) {
try {
/*
* 如果半径小于200则自加否则大于200后重置半径值以实现往复
*/
if (radiu <= 200) {
radiu += 10;
// 刷新View
postInvalidate();
} else {
radiu = 0;
}
// 每执行一次暂停40毫秒
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在activity中启动线程:
new Thread(mCustomView).start();
完整代码
package com.bx.myproject.MyView;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import com.bx.myproject.R;
public class CustomCircle extends View implements Runnable{
private Context mContext;//上下文引用
private Paint mPaint; //画笔
private String mText;
private int mTextColor;
private int mTextSize;
private int radiu;// 圆环半径
public CustomCircle(Context context) {
this(context, null);
}
public CustomCircle(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomCircle(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initPaint();
}
private void initPaint() {
//初始化画笔并打开抗锯齿模式
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
/*
* 设置画笔样式为描边,圆环嘛……当然不能填充不然就么意思了
*
* 画笔样式分三种:
* 1.Paint.Style.STROKE:描边
* 2.Paint.Style.FILL_AND_STROKE:描边并填充
* 3.Paint.Style.FILL:填充
*/
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
// 设置画笔颜色为浅灰色
mPaint.setColor(Color.YELLOW);
/*
* 设置描边的粗细,单位:像素px
* 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
*/
// mPaint.setStrokeWidth(10);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*
* 画一个圆,
* 第一个参数为水平方向的中心坐标
* 第二个参数为垂直方向的中心坐标
* 第三个参数为圆的半径
* 第四个参数为我们的画笔
* */
canvas.drawCircle(MeasureUtil.getScreenSize((Activity) mContext)[0] / 2, 300, radiu, mPaint);
}
@Override
public void run() {
/*
* 确保线程不断执行不断刷新界面
*/
while (true) {
try {
/*
* 如果半径小于200则自加否则大于200后重置半径值以实现往复
*/
if (radiu <= 200) {
radiu += 10;
// 刷新View
postInvalidate();
} else {
radiu = 0;
}
// 每执行一次暂停40毫秒
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Canvas的常用绘制方法:
方法 | 作用 |
---|---|
drawRect() | 画矩形 |
drawCircle() | 画圆形 |
drawArc() | 画圆弧 |
drawBitmap() | 画Bitmap |
drawOval() | 画椭圆 |
drawRoundRect() | 画圆角矩形 |
好吧,现在我们多少了解了一下自定义View,这仅仅是个开始。