【5年Android从零复盘系列之十】Android自定义View(5):画布Canvas详解(图文)
发布日期:2021-06-29 18:17:41 浏览次数:2 分类:技术文章

本文共 8074 字,大约阅读时间需要 26 分钟。

1.简介

Android系统提供Canvas、Paint 、Path三剑客用于绘制View图形。

如果将自定义View的绘制看作美术课绘画作业的话,

Canvas可视为画板上的空白画布,

Paint可视为画笔,

Path可视为绘画者的执笔路径。

其他坐标系等基础,可参考阅读:

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(); }}

布局文件中使用

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();

转载地址:https://cupster.blog.csdn.net/article/details/112484294 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【5年Android从零复盘系列之十一】Android自定义View(6):画笔Paint
下一篇:【5年Android从零复盘系列之九】Android自定义View(4):自绘式详解(图文)

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月12日 19时23分32秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

领导让我整理上个季度的销售额,幸好我会Python数据分析,你猜我几点下班 2019-04-29
【Python爬虫实战】为何如此痴迷Python?还不是因为爱看小姐姐图 2019-04-29
零基础自学Python,你也可以实现经济独立! 2019-04-29
ElasticSearch与Mysql对比(ElasticSearch常用方法大全,持续更新) 2019-04-29
数字化转型的主干道上,华为云以“三大关键”成企业智能化推手 2019-04-29
数字化为何不走“捷”“径”? 2019-04-29
和总裁、专家交朋友,华为云助推政企智能化升级又做到前面去了 2019-04-29
BCOP章鱼船长,6月22日晚上8点上线薄饼 2019-04-29
为战疫助力,半导体功不可没 2019-04-29
了解这些操作,Python中99%的文件操作都将变得游刃有余! 2019-04-29
知道如何操作还不够!深入了解4大热门机器学习算法 2019-04-29
只有经历过,才能深刻理解的9个编程道理 2019-04-29
发现超能力:这些数据科学技能助你更高效专业 2019-04-29
AI当道,人工智能将如何改变金融业? 2019-04-29
消除性别成见,技术领域需要更多“乘风破浪的姐姐” 2019-04-29
7行代码击败整个金融业,这对20多岁的爱尔兰兄弟是如何做到的? 2019-04-29
2020十大编程博客:私藏的宝藏编程语言博客大放送! 2019-04-29
编程中的角色选择:哪类工作角色最适合你? 2019-04-29
10种算法一文打尽!基本图表算法的视觉化阐释 2019-04-29
未来属于人工智能工程师,但成功转型不容易 2019-04-29