1.简介
Android系统提供Canvas、Paint 、Path三剑客用于绘制View图形。
如果将自定义View的绘制看作美术课绘画作业的话,
Canvas可视为画板上的空白画布,
Paint可视为画笔,
Path可视为绘画者的执笔路径。
其他坐标系等基础,可参考阅读:自定义View(1):基础
2.Canvas 的常用功能
| 方法 | 功能 |
|---|---|
| drawColor() | 设置画布颜色 |
| drawCircle() | 绘制圆形 |
| drawRect() | 绘制矩形 |
| drawRoundRect() | 绘制带圆角的矩形 |
| drawArc() | 绘制扇形 or 弧线 |
| drawPoint() | 绘制点 |
| drawPoints() | 绘制多个点 |
| drawLine() | 绘制线 |
| drawLines() | 绘制多条线 |
| drawOval | 绘制椭圆 |
| drawPath() | 按预设画笔路径,绘制 对应得图形 |
| drawBitmap() | 在指定位置,绘制Bitmap对象 |
| drawText() | 绘制文字 |
| clipPath() | 根据自定义图形裁剪 |
| clipRect() | 按矩形裁剪 |
3. 使用
3.1 drawColor() & drawCircle()
package com.cupster.base_super_resource;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
public class CanvasView extends View {
Paint mPaint;
Path mPath ;
private void initSetting(){
mPaint = new Paint();
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 0. onDraw可能多次调用,每次绘制前都先复原paint&path
mPaint.reset();
mPath.reset();
//1. 设置画布底色
// canvas.drawColor(Color.RED);
// canvas.drawColor(getResources().getColor(R.color.colorAccent));//使用xml定义的全局颜色
canvas.drawColor(Color.parseColor("#e5f7ff"));//使用自定义颜色
// canvas.drawRGB(255 ,0 ,0 );//rgb
// canvas.drawARGB(127 ,255 ,0 ,0 );//argb
//2. 绘制圆
mPaint.setColor(Color.parseColor("#ff8696"));
// 参数1 圆心x ; 参数2 圆心y ; 参数3 半径r ;
canvas.drawCircle(200 ,200,120 ,mPaint);//java代码中直接使用的绘制单位是px,xml中使用的是dp
}
public CanvasView(Context context) {
super(context);
initSetting();
}
public CanvasView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initSetting();
}
public CanvasView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initSetting();
}
public CanvasView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initSetting();
}
}
布局文件中使用
<com.cupster.base_super_resource.CanvasView
android:layout_width="200dp"
android:layout_height="200dp"/>
3.2 DrawRect()
public class CanvasView extends View {
Paint mPaint;
Path mPath ;
private void initSetting(){
mPaint = new Paint();
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 0. onDraw可能多次调用,每次绘制前都先复原paint&path
mPaint.reset();
mPath.reset();
canvas.drawColor(Color.parseColor("#e5f7ff"));//使用自定义颜色
//3. 绘制矩形
mPaint.setColor(Color.parseColor("#ff8696"));
//参数1:矩形【左】上角坐标x;参数2:矩形【左】上角坐标y; 参数3:矩形【右】下角坐标x ;参数4:矩形【右】下角坐标y
canvas.drawRect(50 ,50 ,150 ,250 ,mPaint);
// canvas.drawRect(new Rect(50 ,50 ,250 ,250 ),mPaint);//效果同上
//4. 绘制圆角矩形
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// canvas.drawRoundRect(100, 100, 350, 220, 50, 50, mPaint);
// }
}
public CanvasView(Context context) {
super(context);
initSetting();
}
public CanvasView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initSetting();
}
3.3 drawPoint() & drawPoints()
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 0. onDraw可能多次调用,每次绘制前都先复原paint&path
mPaint.reset();
mPath.reset();
canvas.drawColor(Color.parseColor("#e5f7ff"));//使用自定义颜色
mPaint.setColor(Color.parseColor("#ff8696"));
//. 绘制原点:点形状 大小由 paint决定
mPaint.setStrokeWidth(20);//画笔宽度
mPaint.setAntiAlias(true);//抗锯齿效果
mPaint.setStyle(Paint.Style.STROKE);//描边
mPaint.setStrokeCap(Paint.Cap.ROUND);//设置线头的模式
canvas.drawPoint( 80 ,80,mPaint);//圆心坐标x,y
//绘制多个圆点
// float[] points = {10, 10, 35, 35, 30, 80, 80, 30, 80, 80, 120, 60};
// canvas.drawPoints(points , 2 ,points.length-2 ,mPaint);//画部分点:p1:点集合,两个一组;p2:跳过几个集合参数;p3:使用多少个集合参数;p4:画笔
// canvas.drawPoints(points ,mPaint);//全画
}
3.4 drawOval()
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 0. onDraw可能多次调用,每次绘制前都先复原paint&path
mPaint.reset();
mPath.reset();
canvas.drawColor(Color.parseColor("#e5f7ff"));//使用自定义颜色
mPaint.setColor(Color.parseColor("#ff8696"));
//6. 绘制椭圆
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//参数1:椭圆对应矩形【左】上角坐标x;参数2:椭圆对应矩形【左】上角坐标y; 参数3:椭圆对应矩形【右】下角坐标x ;参数4:椭圆对应矩形【右】下角坐标y
canvas.drawOval(30,30 ,220 ,120,mPaint);
}
3.5 drawLine() & drawLines()
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 0. onDraw可能多次调用,每次绘制前都先复原paint&path
mPaint.reset();
mPath.reset();
canvas.drawColor(Color.parseColor("#e5f7ff"));//使用自定义颜色
mPaint.setColor(Color.parseColor("#ff8696"));
//7. 画线
mPaint.setStrokeWidth(6);
//4个参数值对应的是两端点的坐标
//canvas.drawLine(30,30,120,120,mPaint);
float[] points = {10, 10, 35, 35, 35, 35, 80, 30, 80, 30, 120, 60};
// canvas.drawLines(points ,4 ,points.length -4 ,mPaint);
canvas.drawLines(points ,mPaint);
3.6 绘制弧线 & 扇形
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.reset();
mPath.reset();
canvas.drawColor(Color.parseColor("#e5f7ff"));
mPaint.setColor(Color.parseColor("#000000"));
//8. 画弧线/扇形
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//前4个参数: 所依据的椭圆(圆)对应的矩形--的 左上角顶点坐标 & 右下角顶点坐标
//第5个参数 startAngle:起始角度,x轴方向为0度,【特殊】【顺时针为正角度】
//第6个参数 sweepAngle:扫过的角度,【特殊】【顺时针为正角度】
//第7个参数 useCenter:是否连接到圆心,true对应连接-扇形 ,false对应不连-弧线
canvas.drawArc(30, 30, 200, 200, -90, 90, true, mPaint); // 绘制扇形
mPaint.setStyle(Paint.Style.STROKE);//画弧线需设置描边、不填充
canvas.drawArc(30, 30, 200, 200, 90, 90, false, mPaint); // 绘制弧线
}
}
3.7 绘制path
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.reset();
mPath.reset();
//画坐标轴
mPaint.setColor(Color.parseColor("#101010"));
mPaint.setStyle(Paint.Style.STROKE);
mPath.moveTo(120, 120);//y轴顶点(120,120)
mPath.rLineTo(0, 200);//y轴方向 path移动量
mPath.rLineTo(200, 0);//x轴方向 path移动量
canvas.drawPath(mPath, mPaint);//绘制
}
3.8 裁剪canvas.clipXxx & canvas.clipOutXxx
canvas.save();
canvas.clipRect(0,0,128,128);//裁剪 显示区域
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_fangzi);
canvas.drawBitmap(bitmap
,64 ,64//原bitmap绘制起点坐标
,mPaint);
canvas.restore();
canvas.save();
canvas.clipOutRect(0,0,128,128);//裁剪 显示区域
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_fangzi);
canvas.drawBitmap(bitmap
,64 ,64//原bitmap绘制起点坐标
,mPaint);
canvas.restore();
3.9 canvas变换
canvas.save();
// canvas.rotate(15 );//绕 (0,0)
canvas.rotate(-90 ,130,130);// 绕指定点 【特殊】【顺时针为正值角度】
canvas.translate( -20 ,0);
canvas.scale(1.5f ,1.0f , 130 ,130 );//x缩放倍数 y缩放倍数 ,缩放原点x ,缩放原点y
canvas.skew( 0.0f ,0.5f);//错切 倾斜值
canvas.drawBitmap(BitmapFactory.decodeResource(getResources() ,R.mipmap.ic_fangzi)
,130 ,130//绘制起点坐标
,mPaint);
canvas.restore();
3.10 matrix自定义变换
//1.创建Matrix对象
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_fangzi);
Matrix matrix = new Matrix();
matrix.reset();
//2.几何变换
matrix.postTranslate(0,10);
matrix.postRotate(45,130,130);
matrix.postScale(1.3f,1.3f,130,130);
matrix.postSkew(0,0.3f);
canvas.save();
//3.把几何变换应用到Canvas中
canvas.concat(matrix);
canvas.drawBitmap(bitmap,130,130,mPaint);
canvas.restore();