Android自定义绘制1-1 Plus

news2024/11/16 6:37:29

上一个文章是看着扔物线的视频写的。写玩之后,发现他的文章还有很多内容。尴尬。

接着写呗。

自定义绘制知识的4个级别

1.Canvas的drawXXX()系列方法以及Paint类的一些常见方法。

canvas的drawXXX()是自定义绘制的最基本操作。掌握了这些方法,才知道怎么绘制内容。例如,怎么画圆,怎么画方块,怎么画文字。这些内容再配合Paint的一些常见方法对绘制内容的颜色和风格进行简单配置,就能应付大部分绘制需求了。

2.Paint的完全攻略

Paint可以做的事,不仅仅是设置颜色,阴影,粗细。它可以做的风格真的非常多,非常细。比如双线性过滤,拐角形状,特效。

3.Canvas对绘制的辅助--范围裁切和几何变化。

大多数的时候,他们并不会被用到,但当被用到的时候,都是很酷的功能。

以后再也不要怕设计师设计多炫酷的功能了。

4.使用不同的绘制方法来控制绘制顺序。

 有人说,绘制顺序,我多整几个view给他弄出来,但这样通常都有性能问题。所以我们用绘制顺序解决的也就是性能问题。因为用绘制顺序,一个view就能搞定。

第一个系列的内容,canvas.drawXXX以及paint最基本的使用。

1.一切的开始onDraw()

drawXXX()系列的方法和Paint的基础掌握了,就能够应付简单的绘制需求。它们主要包括:

1.Canvas类下的所有draw打头的方法。例如drawCircle(),drawBitmap()

2.Pain类的几个常用方法,比如:

paint.style 绘制模式
paint.color 设置绘制颜色
paint.strokeWidth 设置线条宽度
paint.isAntiAlias 抗锯齿开关

Canvas.drawColor 颜色填充

这是最基本drawXXX方法,是在整个绘制区,统一涂上指定的颜色。

canvas.drawColor(resources.getColor(R.color.black))

这个就直接把绘制区变黑。

也可以通过透明度设置遮罩。

 类似的还有drawRGB和drawARGB,效果都是一样的。

这类颜色填充方法一般用于在绘制之前设置底色,或者在绘制之后设置半透明蒙版。

drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

前面两个参数是圆心的坐标。第三个是圆的半径。他们共同构成了这个圆的基本信息。第四个参数是Paint.它提供除了基本信息以外的所有风格信息。

在Android中,每个View都有一个自己的坐标系。彼此之间是不影响的。坐标系的原点就是View左上角的那个点。所以当我们设置绘制这个圆的时候,比如我们设置圆中心的坐标是300,300,那么它就是这样的:

 如果你想画的圆不是实心的,而是空心的,可以这样:

paint.style = Paint.Style.STROKE

 这里style有三种模式,fill,stroke,fill_and_stroke。分别是填充,描边,填充和描边。

你在stroke和fill_and_stroke模式下,你还可以设置线条的宽度:

paint.strokeWidth = 20f

 在绘制的时候,为了让图形和文字的边缘更圆滑,往往需要开启抗锯齿:

paint.isAntiAlias = true

那么抗锯齿这么好,为什么不默认开启呢?

实质上,抗锯齿的发生是因为图形分辨率过低,导致人眼察觉出了画面中的像素颗粒而已。

那么,为什么开启抗锯齿,就看起来圆滑了呢?因为抗锯齿的原理是,修改图形边缘的颜色。而让图形看起来更加圆滑。

 可以看到,未开启抗锯齿的时候,所有像素的颜色同样都是黑色。而开启后,边缘的颜色被略微改变了。所以,抗锯齿,会造成图形的失真。

除了drawCircle,还可以画别的图形。

 另外,他还有另外两个重载方法,drawRect(RectF rect, Paint paint) 和 drawRect(Rect rect, Paint paint) ,可以让你直接填写rectF或者rect来绘制矩形。

canvas.drawPoint(50f,50f,paint)

再来看这个drawPoint,就是画点,x和y是点的坐标。点的大小可以通过strokeWidth来设置。

点的形状可以通过strokeCap来设置。

 strokeCap除了ROUND之外还可以用BUTT,和SQUARE

 有点像FILL模式下的drawCircle和drawRect。效果是一样的,看自己喜欢,用哪个。

那么为什么要搞两个API呢?因为drawPoint可以画多个点。

 这里使用drawPoints,可以传递一个数组,这个数组里每两个为一对坐标。

offset参数,是指在数组里跳过几个数字,后面的count就是绘制几个点数。

 paint.style = Paint.Style.FILL
        paint.strokeWidth = 20f
        canvas.drawOval(50f,50f,300f,200f,paint)

paint.style = Paint.Style.STROKE下:

另外,他还有一个重载方法,drawOval(rect:RectF,paint) 也可以使用RectF来绘制。

可以使用drawLine来绘制线:

canvas.drawLine(50f,50f,200f,500f,paint)

 因为这个直接不是封闭图形,所以style对他没有影响。

也可以通过drawLines绘制多个点。也就是drawLine的复制版。

val floatArray = floatArrayOf(20f,20f,50f,50f,100f,100f,120f,300f,200f,400f,200f,100f)
canvas.drawLines(floatArray,paint)

 接着,再来看drawRoundRect,也就是带圆角的矩形。

canvas.drawRoundRect(100f,100f,200f,200f,10f,10f,paint)

接着,再来看drawArc。这个是绘制弧形或者扇形的。

drawArc是使用一个椭圆来描述弧形的。

paint.style = Paint.Style.STROKE
canvas.drawArc(100f,100f,200f,200f,-100f,100f,true,paint)

 

首先,前面4个参数是椭圆的4个边界点的坐标,startAngle是弧形的起始角度。X轴的正向是0度的位置,逆时针为负角度,顺时针为正角度。sweepAngle是弧形划过的角度,注意这里的划过,是指在起始角度顺时针划。userCenter表示起始弧度和划过之后的终点位置是否连接中心点。如果连接了,那就是弧形。如果不连接,那就是扇形。

canvas.drawArc(100f,100f,200f,200f,-100f,100f,false,paint)

 

 我们再来看下fill模式下。

paint.style = Paint.Style.FILL
canvas.drawArc(100f,100f,200f,200f,-100f,100f,true,paint)

paint.style = Paint.Style.FILL
canvas.drawArc(100f,100f,200f,200f,-100f,100f,false,paint)

 

 以上就是cavans所有的简单图形绘制,除了简单图形绘制,还可以使用path绘制复杂的自定义图形。

 drawPath(Path path,Paint paint)

这个方法有点复杂的。

前面说到的方法都是绘制给定的图形。而drawPath可以绘制自定义的图形。像涂鸦板都是用这个方法去做。

这里的path就是描述路径对象。

比如绘制心形:

Path可以描述直线,二次曲线,三次曲线,圆,椭圆,矩形,弧形,圆角矩形,把这些图形结合起来,就可以绘制出很多复杂的图形。

Path有两类方法,一类是直接描述路径,另一类就是辅助的设置或者计算。

 Path的第一类方法:直接描述路径

这一类的方法还可以再细分为2组:添加子图和画线(直线或者曲线)

第一组:addXXx---添加子图形

addCircle(float x, float y, float radius, Direction dir)

添加圆

前三个参数是圆的基本信息,最后一个参数是圆的路径的方向。

不过对于普通情况,填逆时针或者顺时针。没有影响。我们一般需要选择填充图形或者描边。

并且在图形出现相交的时候,我们需要判断填充范围。比如:

 

在使用Path.addCircle新增一个圆之后,就可以使用canvas.drawPath来画出来。

path.addCircle(300f,300f,200f,Path.Direction.CW)
        canvas.drawPath(path,paint)

 除了addCircle,还有别的addOval,添加椭圆,addRect添加矩形,addRoundRect添加圆角矩形,addPath(path)添加另一个path.

上面这几个方法的用法都和addCircle差不多。

第二组方法:xxxTo()-----画线(直线或者曲线)

和第一组方法的区别是第一组是添加完整的封闭图形(addPath除外),这一组只是添加一条线。

lineTo(float x,float y)/ rLineTo(floatx, float y)画直线

从当前位置向目标位置画一条直线。x y 是目标位置的坐标。这两个方法的区别是lineTo的参数是绝对目标,而rLineTo的的参数是相对当前位置的相对坐标。前缀r的意思就是relative,相对的。

当前位置:所谓当前位置指的就是最后一次调用画Path的方法的终点位置。初始值为原点(0,0)

paint.style = Paint.Style.STROKE
        path.lineTo(100f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.rLineTo(100f,0f) //由当前位置(0,0)向正右方100像素的位置画一条直线
        canvas.drawPath(path,paint)

quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2)画二次贝塞尔曲线

这条贝塞尔曲线的起点就是当前位置,而参数中的x1,y1,x2,y2分别是控制点和终点的坐标。

cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)  画三次贝塞尔曲线

和上面二次贝塞尔曲线同理

moveTo(float x, float y)/ rMoveTo(float x, float y)移动到目标位置

不论是直线还是而塞尔曲线,都是以当前位置作为起点,而不能指定起点。但是咱们可以通过moveTo(x, y)或者rMoveTo(x,y)来改变当前位置,从而达到间接的设置这些方法的起点。

 paint.style = Paint.Style.STROKE
        path.lineTo(100f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.moveTo(200f,100f)//移动
        path.lineTo(200f,0f)//画竖线
        canvas.drawPath(path,paint)

 moveTo虽然不能添加图形,但是他可以设置起点。所以这是一个非常重要的辅助方法。

arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle)画弧形

这个方法和canvas.drawArc比起来。少了一个参数useCenter,但是多了一个参数,forceMoveTo.

为啥会这样呢?因为arcTo只用来画弧形,而不能用来画扇形。所以这个参数就没用了。

那么这个forceMoveTo又是啥意思

绘制是抬一下笔过去,还是拖着笔迹过去。区别在于是否留下移动的痕迹。

paint.style = Paint.Style.STROKE
        path.lineTo(100f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.arcTo(100f,100f,300f,300f,-90f,90f,true) //强制移动到弧形起点(无痕迹)
        canvas.drawPath(path,paint)

path.arcTo(100f,100f,300f,300f,-90f,90f,false) //留下痕迹

 

addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)

这又是一个弧形方法。一个addArc,一个arcTo,区别在哪?

其实非常简单,这里少了一个参数 foreceMoveTo,默认为true了。

close()封闭当前子图形

什么是封闭呢,就是由当前位置向当前子图形的起点,画一条线。

先看一下没有封闭的:

 paint.style = Paint.Style.STROKE
        path.moveTo(100f,100f)
        path.lineTo(200f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.lineTo(150f,150f)

如果这个时候我们封闭呢?

paint.style = Paint.Style.STROKE
        path.moveTo(100f,100f)
        path.lineTo(200f,100f) //由当前位置(0,0)向(100,100)画一条直线
        path.lineTo(150f,150f)
        path.close()

 

 大家可能会想到我这个时候,使用lineTo起点也是可以办到的,是的,这个时候和Lineto是完全等价的。

所谓子图形,就是一次不间断的连线。

另外,当style为fill,或者为fill_and_stroke的时候,会自动连线。

Path方法第二类:辅助的设置或计算。

这类方法的使用场景比较少。不必学太多。只学期中一个比较常用的:

setFillType(FillType fillType)

前面有说过,path.setFillType是用来设置图形自相交时的填充算法的。

FillType的取值一共有4个:

1.EVEN_ODD

2.WINDING 默认值

3.INVERSE_EVEN_ODD

4.INVERSE_WINDING

两个前面带有INVERSE前缀的, 是1和2的反色版本。

WINDING是全填充,EVEN_ODD是交叉填充。

这个是简单粗暴版本,也就是通常情况下的。

drawBitmap(Bitmap bitmap, float left, float top, Paint paint)画Bitmap

绘制Bitmap对象,期中left,top是要把bitmap要绘制到的位置坐标。

drawText(String text, float x, float y, Paint paint) 绘制文字

界面里所有显示的内容都是绘制出来的,包括文字。drawText这个方法就是绘制文字的。

参数text就是用来绘制的字符串,x,y是绘制的起点坐标。

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

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

相关文章

JNPF 3.4.5 java+.Net6 旗舰版企业版 简搭-敏捷业务低代码开发平台

JNPF 低代码通常是指APaaS产品,通过为开发者提供可视化的应用开发环境,降低或去除应用开发对原生代码编写的需求量,进而实现便捷构建应用程序的一种解决方案。广义上低代码概念涵盖所有能够完成代码的集成,减少代码开发的应用过程…

在哔站黑马程序员学习Spring—Spring Framework—(二)spring的注解开发学习笔记

一、注解开发spring的强项—>简化开发spring从2.0开始逐步提供了各种各样的注解,到了2.5注解比较完善,到了3.0推出了纯注解开发,使用java类替代配置文件,开启了spring快速开发通道。二、注解开发定义bean不再需要在spring配置文件中定义be…

拷贝实体的工具类---BeanObjectCopyUtils

目录 前言: 第一步:引用的核心类: 第一种:单个实体的拷贝方法 第二种:列表类的实体拷贝方法 第二步:核心方法的介绍: 核心方法一,介绍了实例化的操作: 核心方法二…

CMMI之项目管理类

项目管理类过程域涵盖了与项目的计划、监督和控制相关的项目管理活动。CMMI-DEV 中的七个项目管理类过程域是:• 集成项目管理(Integrated Project Management, IPM)• 项目监督与控制(Project Monitoring and Control…

蓝桥杯:城邦

题目链接 问题描述 答案提交 本题答案是:4046。 运行限制 思路分析 代码(Java) 问题描述 小蓝国是一个水上王国, 有 2021 个城邦, 依次编号 1 到 2021。在任意两 个城邦之间, 都有一座桥直接连接。 为了庆祝小蓝国的传统节日, 小蓝国政府…

登录授权方案:JSON Web Tokens (JWT)

登录授权方案:JSON Web Tokens (JWT) JWT官方文档:https://jwt.io/introduction 1.简介: JWT 即 json web tokens,通过JSON形式作为Web应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输,在数据传…

【博客598】从netfilter hook执行原理分析iptables为什么自定义链无法主动调用只能从其它链跳转过来

从netfilter hook执行原理分析iptables为什么自定义链无法主动调用只能从其它链跳转过来 1、netfilter hook执行原理 netfilter 框架是 Linux 网络子系统里的一个核心模块,iptables 就是基于 netfilter 框架实现的一个网络包处理工具。 netfilter hook被调用后执行…

2023年“科学探索奖”申报启动及指南

2023年“科学探索奖”资助不超过50位青年科学家,每位获奖人5年内将获得总计300万元奖金。今年的申报时间为2023年1月1日至3月15日。获奖名单拟定于2023年8月揭晓。本文知识人网小编整理该奖项的概要及申报指南,以飨读者。“科学探索奖”是一项由科学家主…

【高并发内存池】第二弹之threadcache 线程缓存

1.为什么线程向threadcache申请内存不需要加锁? 因为没有把cache设置成全局变量,而是使用了TLS(线程局部存储),作用是当前内存只可当前线程见到,其他线程没有使用权,避免了加锁的操作,保证了线程数据的独立…

基于paddlex图像分类模型训练(一):图像分类数据集切分:文件夹转化为imagenet训练格式

背景 在使用paddlex GUI训练图像分类时,内部自动对导入的分类文件夹进行细分,本文主要介绍其图像分类数据切分源码,或可作为其他项目储备代码:https://github.com/PaddlePaddle/PaddleX/blob/develop/paddlex/tools/dataset_spli…

[Linux]进程概念以及进程状态

🥁作者: 华丞臧. 📕​​​​专栏:【LINUX】 各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞收藏关注)。如果有错误的地方,欢迎在评论区指出。 推荐一款刷题网站 👉 LeetCode刷题网站 文…

vs2019 + qt5.12.11 打包

目录 你以为打包方式 实际要添加步骤 你以为打包方式 先吐槽一番,感觉vsqt打包有点巨坑,还是说我第一次打包其实都是这样子的 首先我们将生成的.exe弄到一个打包文件夹里面 然后嘞 我用qt自带的打包工具windeployqt exe (因为我的再C盘下…

Mysql基础篇(11)—— MySQL8.0新特性之窗口函数

举例1 假设我现在有这样一个数据表,它显示了某购物网站在每个城市每个区的销售额: CREATE TABLE sales( id INT PRIMARY KEY AUTO_INCREMENT, city VARCHAR(15), county VARCHAR(15), sales_value DECIMAL ); INSERT INTO sales(city,county,sales_val…

【xgboost】XGBoost

XGBoost1. 原理改进及特点1.1 遵循Boosting算法的基本建模流程1.2 平衡精确性与复杂度1.3 降低模型复杂度、提升运行效率1.4 保留部份GBDT属性2. sklearn接口(回归)2.1 导库 & 数据2.2 sklearn api普通训练2.3 sklearn api交叉验证2.4 查看属性接口3. xgboost原生代码(回归…

Redis数据持久化方案

作为集中式缓存的优秀代表,Redis可以帮助我们在项目中完成很多特定的功能。Redis准确的说是一个非关系型数据库,但是由于其超高的并发处理性能,及其对于缓存场景所提供的一系列能力构建,使其成为了分布式系统中的集中缓存的绝佳选…

深入学习Vue.js(十)异步组件和函数式组件

文章目录异步组件需要解决的问题异步组件实现原理1.封装defineAsyncComponent函数2.超时与error3.延迟和Loading组件函数式组件异步组件需要解决的问题 允许用户指定加载出错时要渲染的组件允许用户指定Loading组件,以及展示该组件的延迟时间允许用户设置加载组件的…

8. R语言绘图系统介绍、高级绘图与低级绘图、【绘图参数】、绘图函数包

b站课程视频链接: https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新,但是要花钱,我花99😢😢元买了,感觉讲的没问题,就是知识点结构有点乱,有点废话)&…

筑基一层 —— 高质量C编程建议、详解猜数字游戏

目录 一.修炼必备 二.高质量C编程 2.1 高质量C编程的思维导图(需要思维导图的加qq:972606225获取) 2.2 文件结构 2.3 程序的形式 2.4 命名规则 三.猜数字游戏详解 一.修炼必备 1.入门必备:VS2019社区版,下载地址:Visual S…

torch_geometric -- Pooling Layers

torch_geometric – Pooling Layers global_add_pool 通过在节点维度上添加节点特征来返回批量图级输出,因此对于单个图 它的输出由下式计算 from torch_geometric.nn import global_mean_pool, global_max_pool, global_add_pool import torch as thf [[1,2,3,4…

Wider Face+YOLOV8人脸检测

YOLO系列的算法更新实在太快了,前些天刚学习完YOLOV7,YOLOV8就出来了。今天先理解模型的训练过程,后续再学习V8的网络结构等细节。YOLOV8源码链接:https://github.com/ultralytics/ultralytics1 数据格式转换Wider Face数据格式转…