Android Canvas的使用

news2024/11/24 11:58:58

android.graphics.Canvas 一般在自定义View中,重写 onDraw(Canvas canvas) 方法时用到。

	/**
     * Implement this to do your drawing.
     *
     * @param canvas the canvas on which the background will be drawn
     */
    @Override
    protected void onDraw(Canvas canvas) {
    	super.onDraw(canvas);
		
		canvas.xxx // 自己的逻辑
	}

Paint 的使用

Paint 叫画笔,它决定了颜色、画笔宽度、填充效果等。
Canvas 是搭配 Paint 使用的,使用 Canvas 要先初始化 Paint 。如,

Paint paintPointRed = new Paint();

paintPointRed.setColor(Color.RED); // 设置画笔颜色
paintPointRed.setFlags(Paint.ANTI_ALIAS_FLAG); // 设置抗锯齿
paintPointRed.setStrokeWidth(5f); //设置画笔宽度
paintPointRed.setStyle(Paint.Style.STROKE);// 设置只描边,还有填充、填充且描边可选,默认填充

绘制颜色

Canvas.drawColor(int color) :绘制颜色,参数传具体的颜色值就行。

canvas.drawColor(Color.LTGRAY); 效果就是 View 显示灰色,
在这里插入图片描述

绘制点

Canvas.drawPoint(float x, float y, Paint paint) :在左边(x,y) 处绘制一个点。

Canvas.drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) :根据数组 pts 绘制多个点。

根据传入的单个坐标或者坐标数组画点,

private Paint paintPointRed = new Paint();
private Paint paintPointGreen = new Paint();

paintPointRed.setColor(Color.RED);
paintPointRed.setFlags(Paint.ANTI_ALIAS_FLAG);
paintPointRed.setStrokeWidth(5f);

paintPointGreen.setColor(Color.GREEN);
paintPointGreen.setFlags(Paint.ANTI_ALIAS_FLAG);
paintPointGreen.setStrokeWidth(20f);

canvas.drawPoint(100,50, paintPointRed);
	
canvas.drawPoints(new float[]{
                200,80,
                220,60,
                240,40,
        },paintPointRed);

canvas.drawPoints(new float[]{
                200,200,
                300,300,
                400,400,
                500,500,
                600,600,
        },paintPointGreen);

我用的两种画笔,画笔颜色不同、宽度不同,效果对比,
在这里插入图片描述
从例子中可以看出,画布坐标原点(0,0) 是显示区域左上角 。

画布坐标

默认情况下,坐标原点(0,0) 是显示区域左上角。

使用 Canvas.translate(float dx, float dy) 可以修改画布的坐标原点,

例,先画了点,修改画布坐标原点后,再画同样的点,

		canvas.drawPoint(100,50, paintPointRed);
        canvas.drawPoints(new float[]{
                200,80,
                220,60,
                240,40,
        },paintPointRed);

        canvas.drawPoints(new float[]{
                200,200,
                300,300,
                400,400,
                500,500,
                600,600,
        },paintPointGreen);

        canvas.translate(800,0);  //修改画布坐标原点
        canvas.drawPoint(100,50, paintPointRed);
        canvas.drawPoints(new float[]{
                200,80,
                220,60,
                240,40,
        },paintPointRed);

        canvas.drawPoints(new float[]{
                200,200,
                300,300,
                400,400,
                500,500,
                600,600,
        },paintPointGreen);

效果如图,说明画布坐标原点已经变更了。画布坐标原点不同,显示效果不同,so ,变更画布坐标原点有风险,修改需谨慎。
在这里插入图片描述

绘制直线

Canvas.drawLine(float startX, float startY, float stopX, float stopY,NonNull Paint paint) :通过两个点 (startX, startY) 、(stopX, stopY) 确定一条直线。

画笔决定线条的颜色、宽度等。

private Paint paintLine1 = new Paint();
private Paint paintLine2 = new Paint();

paintLine1.setColor(Color.RED);
paintLine1.setFlags(Paint.ANTI_ALIAS_FLAG);
paintLine2.setColor(Color.YELLOW);
paintLine2.setFlags(Paint.ANTI_ALIAS_FLAG);
paintLine2.setStrokeWidth(20f);

canvas.drawLine(100,100, 500,100, paintLine1);
canvas.drawLine(100,200, 500,400, paintLine1);
canvas.drawLine(100,500, 200,600, paintLine2);

效果,
在这里插入图片描述

绘制曲线

Canvas.drawPath(@NonNull Path path, @NonNull Paint paint) :通过 Path 构建贝塞尔曲线,依据 path 画出曲线。

private Paint paintLinePath = new Paint();
paintLinePath.setColor(Color.MAGENTA);
paintLinePath.setFlags(Paint.ANTI_ALIAS_FLAG);
paintLinePath.setStrokeWidth(5f);

Path path = new Path();
path.moveTo(200,200);
path.cubicTo(200,700,800,700, 1000,300);
canvas.drawPath(path, paintLinePath);

效果,
在这里插入图片描述
不对啊,说是画线,怎么出来个图像,按理应该只有下面弧形才对。

不着急,这和画笔的 Style 有关,默认是填充效果 Paint.Style.FILL ,修改为描边效果 Paint.Style.STROKE

paintLinePath.setStyle(Paint.Style.FILL);

效果如图,nice
在这里插入图片描述

绘制文字

drawText(String text, float x, float y, Paint paint) :在坐标 (x,y) 处绘制文本。

drawText(String text, int start, int end, float x, float y,Paint paint) :在坐标 (x,y) 处绘制文本,文本只显示第 start 到第 end-1 位 。

canvas.drawText("CanvasActivity", 100 , 300, paintText);
canvas.drawText("CanvasActivity", 2,9,100 , 350, paintText);

效果,
在这里插入图片描述

绘制圆形

Canvas.drawCircle(float cx, float cy, float radius, Paint paint) :以坐标 (cx,cy) 为圆心绘制半径为 radius 的圆形。

private Paint paintCircleMagenta = new Paint();
private Paint paintCircleGreen = new Paint();

paintCircleMagenta.setColor(Color.MAGENTA);
paintCircleMagenta.setFlags(Paint.ANTI_ALIAS_FLAG);
paintCircleGreen.setColor(Color.GREEN);
paintCircleGreen.setFlags(Paint.ANTI_ALIAS_FLAG);

canvas.drawCircle(100,100,50, paintCircleMagenta);

canvas.drawCircle(400,300,100, paintCircleGreen);

canvas.drawCircle(700,300,100, paintCircleGreen);
canvas.drawCircle(700,300,50, paintCircleMagenta);

canvas.drawCircle(1000,300,50, paintCircleMagenta);
canvas.drawCircle(1000,300,100, paintCircleGreen);

效果,
在这里插入图片描述

说明后面绘制的图像会覆盖前面绘制的。

绘制椭圆

Canvas.drawOval(RectF oval, Paint paint) :通过 RectF 确定椭圆位置并绘制。
RectF(float left, float top, float right, float bottom) : 初始化 RectF 时根据坐标 (left,top)、(right,bottom) 确定矩形的左上角、右下角,得到最大内切椭圆。

Canvas.drawOval(float left, float top, float right, float bottom, Paint paint) :通过坐标确定椭圆位置并绘制。

个人理解,根据坐标得到矩形,矩形确定最大内切椭圆。

private Paint paintOval1 = new Paint();
paintOval1.setColor(Color.BLUE);
paintOval1.setFlags(Paint.ANTI_ALIAS_FLAG);

canvas.drawOval(new RectF(100,100,300,300), paintOval1);
canvas.drawOval(new RectF(400,100,800,300), paintOval1);

paintOval1.setStyle(Paint.Style.STROKE);//只描边
paintOval1.setStrokeWidth(5f);
canvas.drawOval(900,100,1100,600, paintOval1);

效果,
在这里插入图片描述

绘制弧形

Canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) :通过 RectF 确定弧形位置并绘制。
Canvas.drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, Paint paint) :通过坐标确定弧形位置并绘制 。

个人理解,根据坐标得到矩形,矩形确定最大内切椭圆,根据参数来截取椭圆区域得到弧形。

private Paint paintArc1 = new Paint();
paintArc1.setColor(Color.CYAN);
paintArc1.setFlags(Paint.ANTI_ALIAS_FLAG);
        
canvas.drawRect(100,100 ,400,300,paintRect3); // 同位置绘制矩形
canvas.drawArc(100,100,400,300,0,90,false,paintArc1);

canvas.drawRect(100,500 ,400,700,paintRect3);// 同位置绘制矩形
canvas.drawArc(new RectF(100,500,400,700),270,-90,true,paintArc1);

在同位置先绘制了矩形,方便对比,
效果
在这里插入图片描述
以 canvas.drawArc(new RectF(100,500,400,700),270,-90,true,paintArc1); 为例说明参数

  • 矩形左上角坐标是(100,500) ,右下角坐标是 (400,700) ,从而得到了最大内切椭圆。
  • startAngle :开始点相对比 0° 的角度,顺时针方向(绿色箭头方向)为正方向,所以是 270°。
  • sweepAngle :开始点旋转的角度,逆时针方向(蓝色箭头方向)为负方向,所以是 -90° 。
  • useCenter :如果设为 true ,则包含椭圆中心,即弧形区域是 起点终点间的弧线 + 起点和椭圆中心的直线 + 终点和椭圆中心的直线 围起来的区域。为 false ,弧形区域是 起点终点间的弧线 + 起点到终点的直线 围起来的区域。
    在这里插入图片描述

绘制矩形

Canvas.drawRect(@NonNull RectF rect, @NonNull Paint paint) :通过 RectF 确定矩形位置并绘制。

RectF(float left, float top, float right, float bottom) : 初始化 RectF 时根据坐标 (left,top)、(right,bottom) 确定矩形的左上角、右下角。

private Paint paintCircleGreen = new Paint();
private Paint paintRectMagenta = new Paint();
paintRectMagenta.setColor(Color.MAGENTA);
paintRectMagenta.setFlags(Paint.ANTI_ALIAS_FLAG);
paintRectGreen.setColor(Color.GREEN);
paintRectGreen.setFlags(Paint.ANTI_ALIAS_FLAG);

canvas.drawRect(new RectF(100,100,500,300), paintRectMagenta);
canvas.drawRect(new RectF(500,300,700,500), paintRectGreen);

paintRectGreen.setStyle(Paint.Style.STROKE);// 只描边
paintRectGreen.setStrokeWidth(5f);
canvas.drawRect(new RectF(800,300,1000,500), paintRectGreen);

效果,
在这里插入图片描述

绘制圆角矩形

Canvas.drawRoundRect(RectF rect, float rx, float ry, @NonNull Paint paint) :通过 RectF 确定圆角矩形位置并绘制。

Canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) : 通过坐标确定圆角矩形位置并绘制,rx 、ry 决定圆角的弧度。

private Paint paintRoundRect = new Paint();
paintRoundRect.setColor(Color.MAGENTA);
paintRoundRect.setFlags(Paint.ANTI_ALIAS_FLAG);

canvas.drawRoundRect(new RectF(100,100,300,300), 10,10,paintRoundRect);
canvas.drawRoundRect(new RectF(500,100,700,300), 50,50,paintRoundRect);

canvas.drawRoundRect(new RectF(100,400,400,600), 10,10,paintRoundRect);
canvas.drawRoundRect(new RectF(500,400,800,600), 100,100,paintRoundRect);

paintRoundRect.setStyle(Paint.Style.STROKE);// 只描边
paintRoundRect.setStrokeWidth(5f);
canvas.drawRoundRect(new RectF(900,100,1100,300), 10 ,10, paintRoundRect);
canvas.drawRoundRect(new RectF(900,400,1200,600), 100 ,100, paintRoundRect);

效果,
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/970532.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode 剑指 Offer 10- I. 斐波那契数列

LeetCode 剑指 Offer 10- I. 斐波那契数列 题目描述 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下: F(0) 0, F(1) 1 F(N) F(N - 1) F(N - …

LeetCode 46题:全排列

题目 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2: 输入:…

Bridge Champ举办人机对战赛:NFT游戏与传统竞技共生发展编织新格局

概要 现在,NFT与体育竞技正日益紧密地联系在一起。一些体育项目开始推出与赛事或球队相关的NFT,同时也有部分NFT游戏开始举办电子竞技赛事。这种共生发展正在改变体育竞技的生态。 笔者采访了桥牌冠军项目相关负责人,探讨NFT游戏与传统体育竞技的融合潜力。桥牌冠军近期成功举…

您必须尝试的 4 种经典特征提取技术!

一、说明 特征提取如何实现?其手段并不是很多,有四个基本方法,作为AI工程师不能不知。因此,本篇将对四种特征提取给出系统的方法。 二、概述 图像分类长期以来一直是计算机视觉领域的热门话题,并希望能够保持这种状态。…

MES系统质量检查:提升制造业生产质量

一、MES系统质量检查的定义: MES系统质量检查是指制造执行系统中的质量管理模块,旨在监控和管理生产过程中的质量控制和质量检查活动。该模块涵盖了产品质量数据的采集、分析、报告和追溯等功能,以确保产品符合质量要求,并提供实…

技术人的修炼---九五小庞

当一个人在一个领域做了很长时间后,很容易形成一些固化的认识,而且变得封闭,不愿意接受而这个认识的观点。这儿举一个我自己的例子: (建立固化认识)我做用增做了很多年,我自己建立一个很深的认识『产品价值是一切业务增…

轻松敏捷开发流程之Scrum

Scrum是一种敏捷开发流程,它旨在使软件开发更加高效和灵活。Scrum将软件开发过程分为多个短期、可重复的阶段,称为“Sprint”。每个Sprint通常为两周,旨在完成一部分开发任务。 在Scrum中,有一个明确的角色分工: 产品…

智能座舱域集中驶入「深水区」,这些细分赛道迎来变局!

在“移动出行第三空间”概念的指引下,融合视觉、听觉、触觉、文本等多维感知信息的多模态交互,正打破单模态输入输出限制,深度应用于智能座舱。 比如,叠加大屏化、多屏化、AR全息无屏化趋势,多模态识别与大屏&多屏…

iTOP-RK3568开发板驱动指南第五篇-中断

文档教程更新至第五篇 第1篇 驱动基础篇 第2篇 字符设备基础 第3篇 并发与竞争 第4篇 高级字符设备进阶 第5篇 中断 未完待续,持续更新中... 视频教程更新至十一期 第一期_驱动基础 第二期_字符设备基础 第三期_并发与竞争 第四期_高级字符设备进阶 第五期…

【数据结构-队列】队列介绍

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

三维模型OBJ格式轻量化纹理压缩技术方法浅析

三维模型OBJ格式轻量化纹理压缩技术方法浅析 三维模型的OBJ格式轻量化中,纹理压缩是一项重要的技术,用于减小模型文件中纹理数据的大小。以下是对三维模型OBJ格式轻量化纹理压缩的关键技术进行分析: 1、纹理图像压缩算法: 纹理图…

RCU501 RMP201-8 KONGSBERG 分布式处理单元

RCU501 RMP201-8 KONGSBERG 分布式处理单元 AutoChief600使用直接安装在主机接线盒中的分布式处理单元。进出发动机的所有信号都在双冗余CAN线路(发动机总线)上传输。 所有不重要的传感器都可以与K-Chief 600报警和监控系统共享,只需要一个主机接口。这一原则大大…

Mybatis--关联关系映射

目录: 1.什么是关联关系映射: 一对一和多对多的区别 2.mybaits中的一对一&一对多关联关系配置 配置generatoeConfig文件 插件自动生成 ​编辑 写sql语句 创建 Ordermapper类 编写接口类 ​编辑 编写接口实现类 编写测试类 测试结果 一对…

19.SPI核心框架简介

目录 SPI物理总线 信号线 spi时序 spi通信模式 常见spi设备 SPI驱动框架简介 spi主机驱动:spi_controller结构体 spi设备驱动:spi_device结构体、spi_driver结构体 spi总线注册:spi_init() spi总线定义:spi_bus_type s…

【LeetCode-中等题】210. 课程表 II

文章目录 题目方法一:bfs方法二:dfs 题目 这一题是在207题的基础上,要统计拓扑排序的顺序集合,所以只需要在207的基础上加入一个将拓扑排序的节点输出即可(有环无拓扑排序) 【LeetCode-中等题】207. 课程表…

LeetCode--HOT100题(47)

目录 题目描述:105. 从前序与中序遍历序列构造二叉树(中等)题目接口解题思路代码 PS: 题目描述:105. 从前序与中序遍历序列构造二叉树(中等) 给定两个整数数组 preorder 和 inorder ,其中 preo…

本地缓存、Redis数据缓存策略

目录 需求看似简单,一取一传但是,又出现了一个新的问题,数据丢了。 一、缓存缓存有哪些分类: 二、分析一下本地缓存的优势三、本地缓存解决方案?1、基于Guava Cache实现本地缓存2、基于Caffeine实现本地缓存3、基于Enc…

华为OD机试-机器人走迷宫

题目描述 机器人走一个迷宫,给出迷宫的x和y(x*y的迷宫)并且迷宫中有障碍物,输入k表示障碍物有k个,并且会将障碍物的坐标挨个输入. 机器人从0,0的位置走到x,y的位置并且只能向x,y增加的方向走,不能回退. 如代码类注释展示的样子,#表示可以走的方格,0代表障碍,机器人从0,0的位置…

【传输层】TCP -- 三次握手四次挥手 | 可靠性与提高性能策略

超时重传机制连接管理机制三次握手四次挥手滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP应用层协议理解 listen 的第二个参数 超时重传机制 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B&#xff1…

日志规范整改

日志框架 日志级别 日志级别从高到低&#xff1a;TRACE < DEBUG < INFO < WARN < ERROR < FATAL 获取应用名字 <springProperty scop"context" name"spring.application.name" source"spring.application.name" defaultVal…