为什么要学自定义View,因为这是一个Android初级工程师到中高阶的必经之路,很多人对自定义View都比较恐惧,包括我自己,学好自定义View需要花费较多时间和精力,但是请不要畏惧,你必须面对,迈过这座大山,你会有不一样的感觉,下面整理了一些自己在学习自定义View的笔记.
当然,自定义View其实也可以很好玩,如果让你自定义View你第一个想绘制的是什么,嗯?那就画一个你想到的东西放松一下吧
思考:生活中绘画是什么样子的呢?让我们想一下需要准备的东西和过程
首先你需要一个画板,画纸,颜料,画笔,嗯没错,你最少需要这些东西
那么在程序中呢?其实也是一样的
1,首先我们定义一个类继承View重写他的onMeasure和onDraw方法
onMeasure中我们要定义画板的大小,
2,onDraw开始绘画,他提供了一个Canvas也就是画板,这个画板的大小是我们之前定义的(onMeasure后的)
有了画板我们还需要什么呢,一支笔Paint,你可以选择任意一种笔,粗的或者细的,红的或者蓝的,
开始涂鸦作画
需要掌握的
//获取测量模式
int specMode = MeasureSpec.getMode(measureSpec);
//获取测量大小
int specSize = MeasureSpec.getSize(measureSpec);
//EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;
//AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST;
//UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;
//设置测量后的大小
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
//画方
canvas.drawRect(RectF rect, Paint paint)
//画圆
canvas.drawOval(float left, float top, float right, float bottom, Paint paint)
//画路径
canvas.drawPath(Path path, Paint paint);
等等...
完整的代码
public class DiyView01 extends View {
private Paint mMouthPaint;
private Paint mBodyPaint;
public DiyView01(Context context) {
this(context, null);
}
public DiyView01(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DiyView01(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
/**
* 获得绘制文本的宽和高
*/
mMouthPaint = new Paint();
mMouthPaint.setColor(Color.GRAY);
mBodyPaint = new Paint();
mBodyPaint.setColor(getContext().getResources().getColor(R.color.colorGreen));
mBodyPaint.setAntiAlias(true);
mBodyPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mBodyPaint.setStrokeWidth(10);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.RED); //设置canvas的背景色
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//画圆 float left, float top, float right, float bottom
RectF rectF = new RectF(80, 280 + (500 - 280) / 2, 600, 1100);
canvas.drawRect(rectF, mBodyPaint);
//画方 颜色是分层次的,第二层能够覆盖第一层的颜色
canvas.drawOval(80, 280, 600, 500, mMouthPaint);
Path path = new Path();
//移动到
path.moveTo(600, 500);
//画线并移动到
path.lineTo(500, 540);
//画曲线
path.quadTo(1200, 900, 600, 900);
path.lineTo(600, 940);
path.quadTo(1200, 900, 600, 500);
//关闭
path.close();
//画路径
canvas.drawPath(path, mBodyPaint);
}
}
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int result = 0;
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = specSize;
// result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = result < specSize ? result : specSize;
}
}
return result;
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int result = 0;
if (specMode == MeasureSpec.EXACTLY) {
return specSize;
} else {
result = specSize;
// result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
}