自定义控件 (?/N) - 颜料 Paint

news2024/9/28 7:33:40

参考来源

一、颜色

1.1 直接设置颜色

1.1.1 setColor( )

public void setColor(@ColorInt int color)

paint.setColor(Color.RED)
paint.setColor(Color.parseColor("#009688"))

1.1.2 setARGB( ) 

public void setARGB(int a, int r, int g, int b)
paint.setARGB(100, 255, 43, 1)

 1.2 设置着色器 setShader( )

Shader 着色器,设置的是一个颜色规则。使用着色器后直接设置颜色的两种方式 setColor( ) 和 setARGB( ) 就不再起作用。

public Shader setShader(Shader shader)
tile是端点范围之外的着色模式,CLAMP会在端点之外散开端点处颜色、MIRROR镜像、REPEAT重复。
线性渐变

public LinearGradient(float x0, float y0, float x1, float y1, @ColorInt int color0, @ColorInt int color1, @NonNull TileMode tile)

设置两个点和两种颜色,以这两个点为端点,使用两种颜色的渐变来绘制颜色。

辐射渐变

RadialGradient(float centerX, float centerY, float radius, @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode)

centerX,centerY辐射中心坐标、radius辐射半径、centerColor中心颜色、edgeColor边缘颜色、辐射范围之外的着色模式。

扫描渐变

public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1)

cx,cy中心点坐标、color0起始颜色、color1终止颜色。

Bitmap着色器

public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)

tileX 横向的规则、tileY纵向的规则。

混合着色器

public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode) 

shaderA,shaderB 需要混合使用的两个着色器、mode 叠加模式即如何共同绘制。

 1.2.1 线性渐变 LinearGradient

val shader = LinearGradient(100F, 100F, 500F, 500F, Color.parseColor("#E91E63"), Color.parseColor("#2196F3"), Shader.TileMode.CLAMP)
paint.setShader(shader)

1.2.2 辐射渐变 RadialGradient

val shader = RadialGradient(300F, 200F, 200F, Color.parseColor("#E91E63"), Color.parseColor("#2196F3"), Shader.TileMode.CLAMP)
paint.setShader(shader)

1.2.3 扫描渐变 SeepGradient

val shader = SweepGradient(300F, 300F, Color.parseColor("#E91E63"), Color.parseColor("#2196F3"))
paint.setShader(shader)

1.2.4 Bitmap着色器 BitmapShader

val bitmap = BitmapFactory.decodeResource(resources, R.drawable.betman)
val shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
paint.setShader(shader)

如果想绘制圆形的 Bitmap 就别用 drawBitmap() 改用 drawCircle()+BitmapShader 就行,其他形状同理。 

 

1.2.5 组合着色器 ComposeShader

PorterDuff.Mode 用来指定两个图像共同绘制时的颜色策略(确定两者叠加后的颜色)。可以分为两类:一类是Alpah合成,共12种,都是关于aplha通道(透明度)计算的,PorterDuff是两个共同发表算法论文人的姓。另一类是混合,Photoshop等制图软件里都有的那些模式,为了方便也被加了进来。

Alpha合成

混合

 

val bitmap1 = BitmapFactory.decodeResource(resources, R.drawable.betman)
val shader1 = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
val bitmap2 = BitmapFactory.decodeResource(resources, R.drawable.logo)
val shader2 = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
val shader3 = ComposeShader(shader1, shader2, PorterDuff.Mode.SRC_OVER)
paint.setShader(shader3)

1.3 设置颜色过滤 setColorFilter( )

为绘制的内容设置统一的过滤策略,Canvas.drawXXX()会对每个像素进行过滤后再绘制出来。

public ColorFilter setColorFilter(ColorFilter filter)

使用的是 ColorFilter的 三个子类,见下表。

LightingColorFilter

public LightingColorFilter(@ColorInt int mul, @ColorInt int add)

模拟简单光照效果。mul用来和目标像素相乘,add用来和目标像素相加,算法:

R' = R * mul.R / 0xff + add.R
G' = G * mul.G / 0xff + add.G
B' = B * mul.B / 0xff + add.B

PorterDuffColorFilter

public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode) 

使用一个指定颜色和一个指定 PorterDuff 模式来与绘制对象进行合成。color指定的颜色、mode指定的模式。(与ComposeShader不同的是只能指定颜色而不是Bitmap)

ColorMatrixColorFilter

public ColorMatrixColorFilter(@NonNull ColorMatrix matrix)

使用颜色矩阵对颜色进行处理。算法:

R' = a * R + b * G + c * B + d * A + e
G' = f * R + g * G + h * B + i * A + j
B' = k * R + l * G + m * B + n * A + o
A' = p * R + q * G + r * B + s * A + t

paint.colorFilter = LightingColorFilter(0x123456,0xABCDEF)
// R' = R * 0x12 / 0xff + 0xAB
// G' = G * 0x34 / 0xff + 0xCD
// B' = B * 0x56 / 0xff + 0xEF
LightingColorFilter(0x00ffff, 0x000000)    //去掉红色
// R' = R * 0x0 / 0xff + 0x0 = 0 
LightingColorFilter(0xffffff, 0x003000)    //绿色加强
// G' = G * 0xff / 0xff + 0x30 = G + 0x30

1.4 setXfermode( )

要绘制的内容作为源图像,View中已有的内容作为目标图像,指定一个 PorterDuff.Mode 作为绘制内容的颜色处理方案。

public Xfermode setXfermode(Xfermode xfermode)

其它子类已过时,目前只剩下PorterDuffXfermode。

1.4.1 使用离屏缓存 Off-screen Buffer

val xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
...
canvas.drawBitmap(rectBitmap, 0F, 0F, paint)  //画方
paint.xfermode = xfermode
canvas.drawBitmap(CircleBitmap, 0F, 0F, paint)  //画圆
paint.xfermode = null   //用完及时清除

在第二步画圆的时候,跟它共同计算的是第一步绘制的方形。但实际上,却是整个 View 的显示区域都在画圆的时候参与计算,并且 View 自身的底色并不是默认的透明色,而且是遵循一种迷之逻辑,导致不仅绘制的是整个圆的范围,而且在范围之外都变成了黑色。 通过使用离屏缓冲,把要绘制的内容单独绘制在缓冲层, Xfermode 的使用就不会出现奇怪的结果了。

 Canvas.saveLayer( )

做短时的离屏缓存。在绘制代码的前后各加一行代码:在绘制之前保存,绘制之后恢复。

val xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
val saveLayer = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG)    //保存
canvas.drawBitmap(rectBitmap, 0F, 0F, paint)
paint.xfermode = xfermode
canvas.drawBitmap(CircleBitmap, 0F, 0F, paint)
paint.xfermode = null
canvas.restoreToCount(saveLayer)    //恢复

View.setLayerType( )

直接把整个 View 都绘制在离屏缓存中。setLayerType(LAYER_TYPE_HARDWARE) 是使用GPU缓存,setLayerType(LAYER_TYPE_SOFTWARE) 是直接用一个Bitmap缓存。无特殊要求使用上面的 Canvas.saveLayer( ) 以获取更好性能。 

1.4.2 控制好透明区域

除了使用离屏缓存,还要控制透明区域不能太小,须足够覆盖要结合绘制的内容。如下图透明区域过小而覆盖不到的地方,将不会受到 Xfermode 的影响。

二、效果

2.1 抗锯齿 setAntiAlias( )

public void setAntiAlias(boolean aa)

默认是关闭的,开启后让图形或文字的边缘更加平滑(修改图形边缘处的像素颜色使之肉眼看起来更加平滑的感觉)。推荐通过 Paint 的构造设置更便捷。

val paint = Paint(Paint.ANTI_ALIAS_FLAG) //二选一,更推荐
paint.isAntiAlias = true

2.2 绘制风格 setStyle( )

public void setStyle(Style style)

//FILL填充、STROKE画线、FILL_AND_STROKE既画线又填充。

paint.style = Paint.Style.FILL

2.3 线条形状

线条宽度

public void setStrokeWidth(float width)

单位为像素,默认0。0和1的区别见下方几何变换。

线头形状

public void setStrokeCap(Cap cap)

默认BUTT平头、ROUND圆头、SQUARE方头。

拐角形状

public void setStrokeJoin(Join join)

默认MITER尖角、 BEVEL平角、ROUND圆角。

尖角拐角延长线最大值

public void setStrokeMiter(float miter)

当拐角形状是MITER尖角时,拐角处的边缘需要使用延长线来补偿。

2.3.1 setTtrokeWidth( )

paint.strokeWidth = 3F

2.3.2 setStrokeCap( )

paint.strokeCap = Paint.Cap.ROUND

2.3.3 setStrokeJoin( )

paint.strokeJoin = Paint.Join.BEVEL

2.3.4 setStrokeMiter( )

 

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

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

相关文章

多商户商城系统-v2.2.3版本发布

likeshop多商户商城系统-v2.2.3版本发布了!主要更新内容如下 新增 1.用户端退出账号功能 优化 1.平台添加营业执照保存异常问题 2.平台端分销商品优化-只显示参与分销的商品 3.优化订单详情显示营销价格标签 4.平台交易设置增加默认值 5.种草社区评论调整&a…

如何下载安装驱动

1 打开浏览器 这里以Edge浏览器举例 第一步打开桌面上的Edge浏览器 如果您的桌面上没有 那么找到搜索栏 搜索Edge 然后打开 打开之后一般是这样 然后把我发送您的地址 驱动下载地址 https://t.lenovo.com.cn/yfeyfYyD (这个网址只是一个例子) 删除掉前…

MQ主流中间件

MQ主流中间件 目前,在消息中间件的领域中,主流的组件包括以下几种: Apache Kafka:一个分布式流处理平台,可以用于构建实时数据管道和流式应用程序。 RabbitMQ:一个实现了 AMQP(高级消息队列协…

【Spring Security第一篇】初始Spring Security、表单认证、认证与授权

文章目录 一、初识Spring Security1. Spring Security简介2. 第一个Spring Security项目(XML文件配置)3. 第一个Spring Security项目(自动配置)4. 配置Security账户 二、表单认证1. Web 应用中基于密码的身份认证机制2. 默认表单认…

基于 Rainbond 的混合云管理解决方案

内容概要:文章探讨了混合云场景中的难点、要点,以及Rainbond平台在跨云平台的混合云管理方面的解决方案。包括通过通过统一控制台对多集群中的容器进行编排和管理,实现了对混合云中应用的一致性管理。文章还介绍了Rainbond平台在混合云环境下…

程序员的新电脑应该安装那些环境呢?

换新电脑了,那么作为一名程序员需要安装那些软件呢? 电脑系统版本:Windows11 注意:用户名一定要设置成英文的,否则后面会出现一定的问题!! 1、配置环境 (1)JDK环境 h…

HIEE300024R4 UAA326A04电流、电压、功率测量机电指示仪表的选用

​ HIEE300024R4 UAA326A04电流、电压、功率测量机电指示仪表的选用 电流、电压、功率测量机电指示仪表的选用 用于测量电流和电压的仪器类型如下 不 乐器 适用于 1个 PMMC(永磁动圈) 直流电流 2个 动铁式 交直流 3个 电测力计式 …

vcruntime140_1.dll丢失的解决方法

vcruntime140_1.dll是Microsoft Visual C Redistributable中的一个动态链接库(DLL)文件,是电脑Windows系统中重要的文件,丢失会造成很多软件报错无法运行。有不少小伙伴在打开ps,pr或者游戏的过程中都遇到过这个问题&a…

辅助驾驶功能开发-功能规范篇(16)-2-领航辅助系统NAP-巡航跟车基础功能

接上篇博文 2.3.2.巡航跟车基础功能 巡航跟车基础功能介绍辅助驾驶系统的车速设定,车间时距设定,纵向定速巡航、跟车加减速、起停,横向居中控制,弯道控制等逻辑。 前置条件: (1)NOA功能激活; 2.3.2.1.车速调节 1)激活时初始显示 中控屏设置界面有“融合限速设置”的开…

成功上岸国科大研究生!

Datawhale干货 作者:罗龙,江西财经大学,Datawhale优秀助教 中国科学院大学简介 中国科学院大学(University of Chinese Academy of Sciences),简称“国科大”,是一所以研究生教育为主的科教融合…

我群 300+人已熟练使用的 ChatGPT Prompt 技巧

这是吴恩达联合 OpenAI 官方录制的 ChatGPT Prompt 免费视频课,最后一个总结,视频: https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/2/guidelines 在这一节中,我会分享两个技巧:Transforming 和 Expanding …

搭建electron-vue下

搭建electron-vue下 npm install 后续问题Version 9 of Highlight.js has reached EOL. npm run dev 后续ReferenceError: Unknown plugin "component" specified in ...Error: Cannot find module electron-logCant resolve axios inCant resolve vue-electronCant …

day1_内存区域

文章目录 1 程序计数器2 虚拟机栈(JVM 栈)2.1 基本概念以及演示2.2 栈内存溢出的情况2. 3 线程排查 3 本地方法栈4 堆4.1 堆内存溢出以及诊断 5 方法区 JVM的内存区域,主要分为了5个部分: 方法区, 堆, 程序计数器, 虚拟机栈&#…

解读Toolformer

【引子】读论文Toolformer: Language Models Can Teach Themselves to Use Tools,https://arxiv.org/pdf/2302.04761.pdf,再阅读了几篇关于Toolformer的网络热文,于是“无知者无畏”,开始自不量力地试图解读Toolformer。 大语言模…

《数据安全法》

中华人民共和国数据安全法 (2021年6月10日第十三届全国人民代表大会常务委员会第二十九次会议通过) 目录 第一章 总则 第二章 数据安全与发展 第三章 数据安全制度 第四章 数据安全保护义务 第五章 政务数据安全与开放 第六章 法律责任 第…

Gradio学习笔记--Gradio基本用法和简单案例

​​​​​​​ 目录 1--配置Gradio 2--Hello World案例 2-1--基本使用 2-2--进阶使用 3--图像案例 3--常用类 Interface 和 Blocks 1--配置Gradio 使用 pip 安装 Gradio: pip install gradio 2--Hello World案例 2-1--基本使用 import gradio as grdef …

代码随想录算法训练营第二十八天 | 三个逗点四个子串的类型题、子集题要取所有节点、子集与树层去重

93.复原IP地址 文档讲解:代码随想录 (programmercarl.com) 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili 状态:不会做。这是三个逗点四个子串的类型题。 思路 这是切割…

重新定义分析 - EventBridge 实时事件分析平台发布

对于日志分析大家可能并不陌生,在分布式计算、大数据处理和 Spark 等开源分析框架的支持下,每天可以对潜在的数百万日志进行分析。 事件分析则和日志分析是两个完全不同的领域,事件分析对实时性的要求更高,需要磨平事件领域中从半…

【STM32】基础知识 第十一课 时钟

【STM32】基础知识 第十一课 时钟 概述时钟系统的基本概念什么是时钟时钟树锁相环APB 时钟树F1 系列时钟树F4 系列时钟树F7 系列时钟树H7 系列时钟树 系统时钟配置系统时钟配置步骤外设时钟的使能和使能HAL_RCC_OscConfig() 函数HAL_RCC_ClockConfig() 函数 概述 STM32 微控制…

超级香,分享8个相见恨晚的Python库

看到新奇又实用的第三方库,当然要分享出来咯~ Plottable Plottable是一个Python库,用于在matplotlib基础上绘制精美表格。例如下图所示表格。 代码如下: import matplotlib.pyplot as plt import numpy as np import pandas as pd from ma…