前面Android自定义View之ViewGroup描述了自定义ViewGroup以及View的onMeasure,onLayout,draw过程。对于draw是如何去绘制View的,我们怎么能够自己绘制出一些UI效果,这需要对api有一定熟悉程度才能达到。
这里推荐启舰关于自定义控件的系列文章
Android自定义控件三部曲文章索引
本文参考其文章并做一些简单的归纳总结。
一 简单的一个自定义View
- Paint笔:大小,粗细,画笔颜色,透明度,字体的样式等等
- Canvas纸-画布:圆形,矩形,文字等相关的在Canvas里生成
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.example.draw.MyDraw
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
private Paint mPaint;
public MyDraw(final Context context) {
super(context);
init(context);
}
public MyDraw(final Context context, @Nullable final AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyDraw(final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public MyDraw(final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr, final int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(final Context context) {
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setAntiAlias(true);//使用抗锯齿
mPaint.setColor(Color.RED);//画笔颜色
mPaint.setStyle(Paint.Style.FILL);//填充样式
mPaint.setStrokeWidth(20);//画笔宽度
//画第一个实心圆
canvas.drawRGB(0,255,0);
canvas.drawCircle(200,200,100,mPaint);
//画边框圆
mPaint.setStyle(Paint.Style.STROKE);//填充样式
canvas.drawCircle(420,200,100,mPaint);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//填充样式
canvas.drawCircle(640,200,100,mPaint);
}
}
上面是一个最简单的自定View,第一步定义了一只画笔,注意其宽度设置为了20。给画布设置了背景颜色绿色,大家思考下这个时候绿色是充满父控件还是自适应?(充满,原因Android自定义View工作原理关于measure、layout、draw详解)。
第二步画一个圆 分别传入x,y的坐标值以及半径和画笔。
第三步 改变画笔的填充样式 画第二个和第三个圆。大家注意看第二个原就知道 mPaint.setStrokeWidth(20);设置画笔宽度意义
二 关于一些常用api
public class MyDraw1 extends View {
private Paint mPaint;
public MyDraw1(final Context context) {
super(context);
init(context);
}
public MyDraw1(final Context context, @Nullable final AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyDraw1(final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public MyDraw1(final Context context, @Nullable final AttributeSet attrs, final int defStyleAttr, final int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(final Context context) {
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setAntiAlias(true);//使用抗锯齿
mPaint.setColor(Color.RED);//画笔颜色
mPaint.setStyle(Paint.Style.FILL);//填充样式
mPaint.setStrokeWidth(4);//画笔宽度
//画一条线
canvas.drawLine(10, 10, 100, 10, mPaint);
//画多条线
float[] pts = {10, 40, 100, 40, 150, 40, 300, 40};
canvas.drawLines(pts, mPaint);
//画一个点
mPaint.setStrokeWidth(15);
canvas.drawPoint(20, 70, mPaint);
//画多个点
float[] ptPos = {20, 100, 60, 100, 100, 100, 140, 100};
// canvas.drawPoints(ptPos,mPaint);
//int offset:集合中跳过的数值个数,注意不是点的个数!一个点是两个数值;
// count:参与绘制的数值的个数,指pts[]里人数值个数,而不是点的个数,因为一个点是两个数值
//跳过第一个点,画出后面两个点,第四个点不画
canvas.drawPoints(ptPos, 2, 4, mPaint);
// 画矩形
RectF rect = new RectF(20, 200, 210, 250);
RectF rect1 = new RectF(250, 200, 450, 250);
mPaint.setStyle(Paint.Style.STROKE);//填充样式
mPaint.setStrokeWidth(5);
canvas.drawRect(rect,mPaint);
canvas.drawRect(rect1,mPaint);
//画 圆角矩形
// float rx:生成圆角的椭圆的X轴半径
// float ry:生成圆角的椭圆的Y轴半径
RectF rect3 = new RectF(20, 300, 210, 350);
canvas.drawRoundRect(rect3,10,10,mPaint);
//椭圆
//椭圆是根据矩形生成的,以矩形的长为椭圆的X轴,矩形的宽为椭圆的Y轴,建立的椭圆图形
//RectF oval:用来生成椭圆的矩形
RectF rect4 = new RectF(20, 400, 210, 450);
canvas.drawRoundRect(rect4,10,10,mPaint);
canvas.drawOval(rect4,mPaint);
//画圆弧 也是根据矩形生成的
// RectF oval:生成椭圆的矩形
// float startAngle:弧开始的角度,以X轴正方向为0度
// float sweepAngle:弧持续的角度
// boolean useCenter:是否有弧的两边,True,还两边,False,只有一条弧
RectF rect5 = new RectF(20, 500, 210, 550);
canvas.drawArc(rect5,0,90,true,mPaint);
RectF rect6 = new RectF(20, 600, 210, 650);
canvas.drawArc(rect6,0,90,false,mPaint);
}
}
后续关于View的路径文字,canvas等变换操作推荐大家查看Android自定义控件三部曲文章索引