从hencoder上学习关于 paint的知识
HenCoder Android 开发进阶: 自定义 View 1-2 Paint 详解

关于Paint,有四个最重要的API,分别是

  • 颜色
  • 效果
  • drawText()相关
  • 初始化

1、颜色

canvas绘制的内容对颜色有三种处理:

1.1、基本颜色
为像素的基本颜色,根据绘制内容的不同而有不同的控制方式:Canvas的颜色填充类方法drawColor()/RGB()/ARGB()的颜色,是直接写在参数中的,drawBitmap的颜色是由Bitmap对象直接提供的,除此之外,文字和图形的颜色绘制就需要paint的额外参数来设置了。

  1. 直接设置颜色 setColor()
paint.setColor(Color.parseColor("#00FFFF"));
canvas.drawText("rikkatheworld",100,100,paint);
  1. setARGB(int a,int r,int g,int b)
    这三个值为透明度和三原色,实际运用setARGB和setColor效果是一样的
paint.setARGB(100,255,0,0);
canvas.drawRect(0,0,200,200,paint);

setShader(Shader shader) 设置 Shader
除了给paint直接设置颜色,还可以给paint设置Shader,它是一个着色器,是一套设置颜色的方案。
当设置了Shader后,Paint就不会使用setColor或者setARGB里面的颜色了,而是直接使用Shader中的方案。

  1. LinearGradient 线性渐变
    设置两个点和两种颜色,以这两个点作为端点,使用两种颜色的渐变来绘制颜色。比如:
Shader shader = new LinearGradient(100,100,500,500,Color.parseColor("E91E63"),Color.parseColor("#2196F3"),Shader.TileMode.CLAMP);
paint.setShader(shader);
canvas.drawCircle(300,300,200,paint);

效果如下:

其中前4个参数为2个端点的坐标,两个颜色为端点散发出的颜色,最后一个变量Shader.TileMode tile有三种模式:CLAMP、MIRROR、REPEAT,从字面意思上可以得出CLAMP是最正常的模式,其次是镜像最后一个是重复渐变。

  1. RadialGradient 辐射渐变
    就是从圆的中心向外颜色渐变:
Shader shader = new RadialGradient(300, 300, 200, Color.parseColor("#E91E63"),  Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
paint.setShader(shader);
canvas.drawCircle(300,300,200,paint);

前两个参数为圆心,第三个参数为半径,第一个颜色为辐射的中心颜色,第二个则为边缘颜色。效果如下:

3. SweepGradient 扫描渐变
大概是这样:

Shader shader = new SweepGradient(300, 300, 200, Color.parseColor("#E91E63"),  Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
paint.setShader(shader);
canvas.drawCircle(300, 300, 200, paint);

效果如下:

  1. BitmapShader 就是将Bitmap的像素作为图形或者文字的填充
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.batman);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
canvas.drawCircle(300, 300, 200, paint);


没错从上面的效果可以看出 使用drawCircle+BitmapShader 和 drawBitmap效果一样,但是这样可以绘制出圆形的bitmap,比如说头像。

  1. ComposeShader 混合着色器
    就是把两个Shader混在一起用
// 第一个 Shader:头像的 Bitmap
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.batman);
Shader shader1 = new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);// 第二个 Shader:从上到下的线性渐变(由透明到黑色)
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.batman_logo);
Shader shader2 = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);// ComposeShader:结合两个 Shader
Shader shader = new ComposeShader(shader1, shader2, PorterDuff.Mode.SRC_OVER);
paint.setShader(shader);
canvas.drawCircle(300, 300, 300, paint);

PorterDuff.Mode.SRC_OVER:使用了两个bitmap进行叠加绘制。
PorterDuff.Mode是用来指定两个bitmap绘制时的颜色策略。它有17种绘制模式,而 SRC_OVER是最正常最常用的绘制策略。
别的模式可以参考官方文档:官方文档

1.2、setColorFilter(ColorFilter colorFilter)
为颜绘制设置颜色过滤,为绘制的内容建立一个统一的过滤策略,然后 Canvas的drawXXX()会对每个像素都进行过滤然后绘制出来。在paint中使用setColorFilter方法,ColorFilter并不能直接使用,而是要使用它的三个子类:LightingColorFilter PorterDuffColorFilterColorMatrixColorFilter

  1. LightingColorFilter
    用来模拟简单的光照效果
    LightingColorFilter的构造方法是LightingColorFilter(int mul, int add),参数中的mul和add都是和颜色格式相同的int值,其中mul用来和目标像素相乘,add用来和目标像素相加。
R' = R * mul.R / 0xff + add.R
G' = G * mul.G / 0xff + add.G
B' = B * mul.B / 0xff + add.B

一个默认的LightingColorFilter,mul值为0xffffff,add值为0x000000,那么对于一个像素,他的计算过程就是:

R' = R * 0xff / 0xff + 0x0 = R // R' = R
G' = G * 0xff / 0xff + 0x0 = G // G' = G
B' = B * 0xff / 0xff + 0x0 = B // B' = B

如果我们将红色移除,可以把mul值改成 0x00ffff,则R’就计算等于0了。
比如说我们可以把绿色调的更加鲜艳,可以将add改成 0x003000,那么其G’=G+0x30,这时候绿色就更加的鲜艳了~

ColorFilter lightingColorFilter = new LightingColorFilter(0xffffff, 0x003000);
paint.setColorFilter(lightingColorFilter);
  1. PorterDuffColorFilter
    用一个指定的颜色和一个指定的ProterDuff.Mode来对绘制对象进行合成。和之前的ComposeShader相比的区别就是之前是用Bitmap来进行合成,而这次就只能指定用一种颜色源。

  2. ColorMatrixColorFilter
    ColorMatrixColorFilter 使用一个 ColorMatrix 来对颜色进行处理。 ColorMatrix 这个类,内部是一个 4x5 的矩阵:

[ a, b, c, d, e,f, g, h, i, j,k, l, m, n, o,p, q, r, s, t ]

通过计算,ColorMartix可以要把绘制的像素进行转化,对于颜色【R,G,B,A】来说,转化算法是这样的:

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;

还可以通过setSatuation(float sat)来进行设置饱和度,具体如何就不说了。
这里有个通过ColorMatrixColorFilter做的开源滤镜库StyleImageView

以上就是Paint对颜色的第二层处理:通过setColorFilter(colorFilter)来进行像素过滤从而达到加工颜色的效果。
Paint最后一层处理颜色的方法就是setXfermode,它处理的是 [当颜色遇上View] 的问题。

1.3 setXfermode
“Xfermode"其实就是"Transfer mode”,准确的定义是当你要绘制的内容和Canvas的目标位置的内容应该怎样结合计算去得出最终的颜色。通俗地说,其实就是要你以绘制的内容作为源图像,以 View 中已有的内容作为目标图像,选取一个 PorterDuff.Mode 作为绘制内容的颜色处理方案。就像这样:

Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
...
canvas.drawBitmap(rectBitmap, 0, 0, paint); // 画方
paint.setXfermode(xfermode); // 设置 Xfermode
canvas.drawBitmap(circleBitmap, 0, 0, paint); // 画圆
paint.setXfermode(null); // 用完及时清除 Xfermode

得到的效果是这样:


另外,从上面的示例代码可以看出,创建 Xfermode 的时候其实是创建的它的子类 PorterDuffXfermode。而事实上,Xfermode 也只有这一个子类。

使用Xfemode时我们要注意两点:

  1. 使用离屏缓存
    我们实际上在不做处理时使用上述的代码并不能直接得到那么理想的结果,而是:

    这是因为在第二步画圆的时候,和正方形一起进行计算并不是这个圆,而是这个带圆的view,而且因为View的底色并不是默认的透明色,所以导致这些底色也参与了计算,这个时候我们需要开启离屏缓存 (Off-screen Buffer) ,先让绘制的内容在屏幕之外绘制好,最后再贴回view中:

    使用离屏缓存有两种方式:
    (1)Canvas.saveLayer()
    可以做短时间的离屏缓冲。
int saved = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);canvas.drawBitmap(rectBitmap, 0, 0, paint); // 画方
paint.setXfermode(xfermode); // 设置 Xfermode
canvas.drawBitmap(circleBitmap, 0, 0, paint); // 画圆
paint.setXfermode(null); // 用完及时清除 Xfermodecanvas.restoreToCount(saved);

(2)View.setLayerType()
View.setLayerType() 是直接把整个 View 都绘制在离屏缓冲中。 setLayerType(LAYER_TYPE_HARDWARE) 是使用 GPU 来缓冲, setLayerType(LAYER_TYPE_SOFTWARE) 是直接用一个 Bitmap 来缓冲。

  1. 控制好透明区域
    使用Xfermode来绘制内容,除了注意使用离屏缓冲,还要注意控制它的透明区域不要太小,要让它足够覆盖到要和它结合绘制的内容。否则很容易得到你不想要的,比如:

到这里,Paint的第一类API,关于颜色的设置到这里就讲完了,Paint对绘制内容的着色主要包括三层,第一层是通过setColor等api像素进行直接上色,第二类是通过setColoerFilter来对像素进行过滤,就和我们平时相机用到的滤镜似的,最后通过Xfermode来对绘制中出现相遇别的view的时候做一个颜色的处理。

hencoder学习自定义view(1)相关推荐

  1. 自己动手,丰衣足食 —— 学习自定义View(一)

    自己动手,丰衣足食 -- 学习自定义View(一) 前言 我们经常在做项目的时候遇到这样的情况,客户提出需求,UI把设计稿拿出来,你发现直接用现成的开源库好像不行哎,多多少少有些不同.这时候你就会想: ...

  2. # HenCoder Android 自定义 View 1-8 硬件加速

    硬件加速这个词每当被提及,很多人都会感兴趣.这个词给大部分人的概念大致有两个:快速.不稳定.对很多人来说,硬件加速似乎是一个只可远观而不可亵玩的高端科技:是,我听说它很牛逼,但我不敢「乱」用,因为我怕 ...

  3. 以小米时钟为demo学习自定义view过程总结

    首选感谢这位博主的分享,让我等新生有很好的范例学习 http://blog.csdn.net/qq_31715429/article/details/54668668点击打开链接 点击打开链接 点击打 ...

  4. 学习自定义View(二)仿58同城加载

    之前用58同城app的时候看到它的加载界面不错,但是那时候还不知道如何实现~接触自定义View后,于是自己试着模仿写了一个 先看效果图: 录制的GIF上有一点卡,其实在真机上面运行很流畅的~ 其实感觉 ...

  5. 步步学习自定义View:Hencoder 精简版学习笔记(一)

    自定义控件一直是让很多人包括我头疼的地方,难度较高 且学习资料零碎 直到我发现扔物线大神的HenCoder进阶手册. 这篇文章记录一下学习过程,以及途中经过精简的内容.便于日后查阅 1.1 绘制基础 ...

  6. Android开源中国客户端学习 (自定义View)左右滑动控件ScrollLayout

    左右滑动的控件我们使用的也是非常多了,但是基本上都是使用的viewpager 等 android基础的控件,那么我们有么有考虑过查看他的源码进行定制呢?当然,如果你自我感觉非常好的话可以自己定制一个, ...

  7. 自定义view学习-手把手教你制作一个可扩展日历控件

    来看看效果图先,手把手教你实现一个简易,但高扩展度的日历控件,可自由扩展成签到,单选,多选日期. 首先我们来分析实现思路.对于上图的效果,很明显是一个6x7的表格. 我们可以两个for循环控制绘制每个 ...

  8. 自定义view学习-创建自己的九宫格解锁view

    先上效果图 效果如上,接下来是如何实现,并没有那么快上代码,不看代码不舒服的请迅速下翻. 九宫格解锁还是比较经典的,作为学习自定义view的入门. 对于九宫格解锁,我的实现思路是这样的: 1.先在屏幕 ...

  9. Android 自定义View中坐标点的理解学习(一)

    本文主要是记录学习自定义view中看到的资料,为了方便记忆做了保存整理便于自己学习也方便其他Android开发爱好者学习,参考资料看底部链接. 一.getLocationInWindow和getLoc ...

  10. android 自定义view 硬件加速,Android自定义View(八) -- 硬件加速

    Android自定义View(八) – 硬件加速 今天学习自定义View部分的最有一篇:硬件加速因为无法录制GIF,所以本篇内容基本为原博 本文计划根据HenCoder系列文章进行学习,所以代码风格及 ...

最新文章

  1. hk.module must be initialized inside an hk.transform
  2. pygame 学习check_event,game_function,alien_invasion等程序
  3. 数据优化:求求你别再用offset和limit分页了
  4. [LeetCode] Search in Rotated Sorted Array
  5. info matlab,c – 在OpenCV中是否有类似MATLAB的’impixelinfo()’功能?
  6. linux不识别xfs,centos7 grub2无法识别xfs root分区
  7. dedecms读取多个类别信息
  8. 计算机应用基础第3次平时作业,计算机应用基础第3次作业.doc
  9. 毕业设计 - 基于JAVA人脸识别管理系统(人脸搜索与人脸库管理)
  10. w10运行游戏计算机中丢失xinput1-3.dll,win10游戏缺少xinput1_3.dll如何修复_win10电脑找不到xinput1_3.dll怎么解决...
  11. TX2 配置xbox360无线手柄
  12. 适合老爸用的在线的LaTeX数学公式编辑器
  13. Java开源在线商城系统 ostocy-jshop
  14. 什么是数字孪生?已有哪些应用?终于有人讲明白了
  15. SolidWorks 2021 SP5安装流程
  16. 袋鼠过河问题(Java)
  17. 五轴数控转台_RTCP、一次装夹、双转台……这是一份五轴应用说明书
  18. Prince and Princess UVA - 10635
  19. 用c语言求出1加到100的和
  20. 求二阶系统输入单位斜坡响应matlab,二阶系统的斜坡响应教程.docx

热门文章

  1. tomcat 启动编码设置
  2. 物联网中对视频远程传输解决方案
  3. c语言编fft算法程序,用C语言实现FFT算法
  4. MATLAB线性卷积圆周卷积FFT程序
  5. PLC梯形图编程入门
  6. 用Python执行SQL、Excel常见任务?10个方法全搞定!
  7. 材料成形计算机辅助设计,材料成形及控制工程
  8. 04 - 雷达的工作频率
  9. 高性能MySQL系统思维导图
  10. 学会2种方法,小白也能快速产出标准的Axure原型