Canvas 意为画布,对于自定义 View 而言,有了画布,就有了世界。
操作 | API | 备注 |
---|---|---|
绘制颜色 | drawColor, drawRGB, drawARGB | 使用单一颜色填充整个画布 |
绘制形状 | drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc | 点、线、矩形、圆角矩形、椭圆、圆、圆弧 |
绘制文本 | drawText, drawPosText, drawTextOnPath | 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字 |
一、新建自定义 View
- 新建 Java 类,并继承 View
- 重写构造器
- 在构造器中做初始化工作
public class TView extends View {
private Paint mPaint;
//一个参数的构造器在代码中动态构建的时候会被调用
public TView(Context context) {
super(context);
initPaint();
}
//两个参数的构造器在初始化 xml 中的控件时会被调用
public TView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
private void initPaint() {
mPaint = new Paint(); //新建画笔
mPaint.setColor(Color.BLACK); //颜色
mPaint.setStrokeCap(Paint.Cap.ROUND); //点形状,不设置为方形
mPaint.setStyle(Paint.Style.FILL); //填充方式
mPaint.setStrokeWidth(10f); //粗细
}
}
二、绘制点
三个方法:
drawPoint(float x, float y, Paint paint)
drawPoints(float[] pts, Paint paint);
drawPoints(float[] pts, int offset, int count,Paint paint)
通过上面的方法,在 onDraw 方法中绘制点(重写 View 的 onDraw 方法):
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPoint(200,500,mPaint);
canvas.drawPoint(200,600,mPaint);
canvas.drawPoint(200,700,mPaint);
mPaint.setColor(Color.RED);
canvas.drawPoints(new float[]{
400,500,
400,600,
400,700
}
,mPaint);
mPaint.setColor(Color.BLUE);
//第二个参数为跳过前几个数据,第三个参数为数组长度
canvas.drawPoints(new float[]{
600,500,
600,600,
600,700,
600,800,
600,900
},2,10,mPaint);
}
三、绘制线
三个方法:
drawPoint(float x, float y, Paint paint)
drawPoints(float[] pts, Paint paint);
drawPoints(float[] pts, int offset, int count,Paint paint)
和绘制点不同的是,第三个方法中,count 参数为 pts 除去 offset 值剩下的元素个数,且值为 4 的倍数,否则是会抛错的。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(200,100,300,100,mPaint);
mPaint.setColor(Color.RED);
canvas.drawLines(new float[]{
200,200,400,200,
200,300,500,300,
},mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawLines(new float[]{
600,300,700,300,
600,400,800,400,
600,500,900,500
},4,8,mPaint);
}
四、绘制圆
一个方法:
drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
绘制方法比较简单,只要把圆心坐标和半径填入,就可以按照预定的画笔绘制。这里需要注意的是,绘制时根据画笔的 Style 不同,圆形的实际大小会有所不同。
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(500,1000,50,mPaint);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(500,1200,50,mPaint);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(500,1400,50,mPaint);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(2);
根据效果图可以看到,Style 为 Paint.Style.FILL 时,绘制时是不会把画笔粗细算进去的。
五、绘制矩形
三个方法:
drawRect(Rect r, Paint paint)
drawRect(RectF rect, Paint paint)
drawRect(float left, float top, float right, float bottom, Paint paint)
绘制一个矩形需要这个矩形对角两个点的坐标,第一第二种方法原理也是相同的,不过把两个坐标封装到了各自的类中。Rect 和 RectF 在本质上区别不是很大,除了精度不同外,功能是一样的。
下面用三种方法分别绘制
/**绘制矩形*/
canvas.drawRect(100,100,700,300,mPaint);
mPaint.setColor(Color.RED);
Rect rect = new Rect(100,400,700,600);
canvas.drawRect(rect,mPaint);
mPaint.setColor(Color.BLUE);
RectF rectF = new RectF(100,700,700,900);
canvas.drawRect(rectF,mPaint);
六、绘制圆角矩形
两个方法:
drawRoundRect(RectF rect, float rx, float ry, Paint paint)
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)
上面第二种方法是在 API 21 才加入,所以一般绘制时,我们会选择第一种方式绘制。
绘制圆角矩形的参数和绘制矩形相比,多了两个参数: rx ry,这两个参数是圆弧 x 轴上的半径和 y 轴上的半径。我们可以利用这两个参数绘制一个椭圆。
RectF rect = new RectF(100, 100, 700, 300);
// rx 为矩形长的一半,ry 为矩形宽的一半
canvas.drawRoundRect(rect,300,100,mPaint);
mPaint.setColor(Color.BLUE);
RectF rect2 = new RectF(100,400,700,600);
canvas.drawRoundRect(rect2,20,20,mPaint);
七、绘制椭圆
两个方法:
drawOval(RectF rect, float rx, float ry, Paint paint)
drawOval(float left, float top, float right, float bottom, float rx, float ry, Paint paint)
同样的,上面第二种方法是在 API 21 才加入,所以一般绘制时,我们会选择第一种方式绘制。
实际上,绘制椭圆和绘制矩形的 api 几乎是一样的用法,我们用相同的参数分别绘制椭圆和矩形:
可以看到,这个椭圆实际上是矩形的内切,这样就不难理解上面的参数了。
八、绘制圆弧
两个方法
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
同样的,上面第二种方法是在 API 21 才加入,所以一般绘制时,我们会选择第一种方式绘制。
绘制圆弧的前四个参数和椭圆是一样的,startAngle 和 sweepAngle 分别为开始角度和扫过的角度,参数中需要我们注意的是 useCenter。看图
可能换成填充方式看得更明白一些:
由图可以看到,userCenter 表示圆弧是否与圆心连接,当 userCenter 为 true 的时候,形成的是一个由弧形和圆心围成的扇形,当 userCenter 为 false 时,形成的是圆弧和两个端点围成的图形。
Canvas 的图形绘制基本就是以上,通过不同的图形组合,我们已经可以做一些常见的自定义 View ,例如进度条等等。
真的,不难。
感谢 :GcsSloop 自定义 View 系列