专栏名称: 开发者全社区
分享和推送Java/Android方向的技术和文章,让你成为这方面的大牛,让你每天都成长一点。同时,我们也会邀请BAT的大牛分享原创!
目录
相关文章推荐
stormzhang  ·  游戏的玩法,已经变了 ·  11 小时前  
鸿洋  ·  Android从上帝视角来看PackageM ... ·  19 小时前  
stormzhang  ·  不让人们存钱了? ·  昨天  
鸿洋  ·  深入探索 APKTool:Android ... ·  昨天  
鸿洋  ·  Gradle配置,Android应用签名详解 ·  3 天前  
51好读  ›  专栏  ›  开发者全社区

Android Shader 实战 各种炫酷效果的基石

开发者全社区  · 公众号  · android  · 2017-04-15 08:45

正文

相关阅读:

吊炸天!74款APP完整源码!

谈谈我做技术面试官的经历--Android面试官给你的面试题和建议

Android自定义View - 最通俗易懂的自定义View原理系列

来源:http://blog.csdn.net/qian520ao 

源码下载地址:见文末“阅读原文”


自定义view中画笔Paint有设置着色器方法paint.setShader(),我们来看一下这个Shader的子类




1

SweepGradient [雷达实战]



效果图



使用方式



启动雷达 | 关闭雷达 扫描

startScan();   
stopScan();



SweepGradient【梯度渐变】



上图我们可以看到SweepGradient有两个构造方法,分别是多色渐变和两色渐变,我介绍一下各自的参数。




绘制雷达


有了这个SweepGradient,绘制雷达就轻松多了,我们只要把雷达的基线绘制好,然后通过paint处理的着色器绘制渐变的圆进行旋转就是我们所要的雷达效果了。


1.首先我们在values目录下面创建attrs.xml文件,设置自定义view的参数供布局使用



2.在代码中我们获取布局中定义的参数



3.onMeasure的时候,我们根据用户的不同宽高设置,设置对应的布局大小



上述热身运动做完之后我们开始绘制雷达,首先我们将画板canvas移动到屏幕的中心点,然后根据用户设定圆圈个数来绘制圆圈,最后在用设置着色器的paint来绘制过渡颜色的圆,最后进行旋转即可。



初始化paint和shader



我们通过Handler让雷达动起来。


雷达旋转的方法是旋转canvas,这其中有两种实现方式

(Matrix详解http://www.gcssloop.com/customview/Matrix_Basic)





2

BitmapShader [多边形图片实战]




从上图可以看出BitmapShader 只有一个构造方法,



上面的这张德莱文X轴是CLAMP模式,Y轴是REPETA模式,那么问题来了,激光强还是斧头强。



这时候我们如果在onDraw的时候,在中心位置绘制一个圆,那么是不是就能够相当于以上图为背景,扣出一个圆呢。

 //中心画一个半径为宽的圆
canvas.drawCircle(mWidth / 2, 
    mHeight / 2, mWidth / 2, mPaint); 



那么就好理解了,paint设置了BitmapShader相当于绘制了底层的图片背景,你可以设置了BitmapShader之后,canvas用这枝画笔去绘制任何图像,相当于从背景图扣出对应的形状。


有一点要注意的是BitmapShader通过构造函数初始化设置bitmap时候,默认这个着色背景为当前bitmap的大小,可以通过setLocalMatrix去重新设置着色背景的形状/范围



效果图



那么我们撸起袖子来通过这个BitmapShader来绘制多边形,我们首先画一个五角形


思路:


首先我们将中心点移动到五角形的中心,以r为半径,我们睁眼说瞎话的设A角度为0°,那么就可以计算B,C,D,E各自的角度,然后按照我们上片自定义菜单(http://blog.csdn.net/qian520ao/article/details/60509040)得出的公式 


x=Math.sin(2∗PI/360∗angle)∗r 
y=Math.cos(2∗PI/360∗angle)∗r 
x=Math.sin(Math.toRadians(angle))∗r 
y=Math.cos(Math.toRadians(angle))∗r


现在我们就能够求出各个点的坐标了,下面我们看一下绘制流程。 


 

我们的绘制流程是 
0 - 2 - 4 - 1 - 3 - 0 
A - C - E - B - D - A



我们通过比较简单的方法来验证一下我们的计算




根据上面这个点的规律,再加上计算(奇/偶数角度计算方式有点区别),下面我直接po出最后的计算方式,虽然感觉不是很干练[小于4的情况 : Go home, You are drunk]



三十角形

[凶残的德莱文] 




3

LinearGradient [霓虹灯文字实战/图片倒影实战]





不多说了,我们先上代码



 


结合图文我们可以很清晰的看出,我们从左上角到左下角着色LinearGradient,所以当着色背景LinearGradient设置的大小大于或者等于当前显示的范围(rect),那么设置TileMode作用就不大了。


那么我们来试试当着色背景LinearGradient的高度为当前形状1/3的时候,设置不同的TileMode的效果。


onDraw



下面分别是CLAMP [拉伸] MIRROR [镜像] REPEAT [重复]


  


下面我们用LinearGradient开始实战霓虹文字



先放出代码过个瘾



onDraw



xml代码



解刨图 


PS:好气啊,昨晚编辑了这篇文章,写了蛮多的没有保存到线上草稿箱,手抽了一下把浏览器关了…T T,上图原本是有呕心沥血做出,后来被我清除了,大家凑合着看吧。。。。


回归正题,我们来分解一下上面这张图,图片做的是一个效果,但是实际上我理一下,当前我设置的文字颜色是#ff00ff即紫色

getCurrentTextColor(), Color.RED, 
    Color.YELLOW, Color.BLUE, getCurrentTextColor()

所以排序应该是 紫紫紫 紫红黄蓝紫 紫紫紫 ,也就是说红色的左边和蓝色的右边填充的颜色应该是紫色(TileMode为CLAMP),所以我们开始translation的时候就能比较柔和的先显示TextView当前的颜色然后再进行过渡。


我们拿LinearGradient来做一个图片倒影


先拿效果图精神精神 



我们讲一下思路,首先我们需要设置2张bitmap,一张是正序图片,另一张是倒影的图片(都为同张图片),关键是倒影图片设置完之后,我们需要调节一下图片的透明度,这里需要用到Xfermoder的知识(http://blog.csdn.net/harvic880925/article/details/51264653),


我们用LinearGradient绘制出与bitmap相同大小的RectF(dst目标),然后用Xfermode的SRC_OUT模式绘制倒影的bitmap,再加上先前对LinearGradient的颜色设定就能够做到如图的倒影效果了。


总结


最后还剩下RadialGradient水波纹效果(http://blog.csdn.net/harvic880925/article/details/52653811)和ComposeShader(Shader),有兴趣的可以捯饬捯饬。


通过上面三个实战,我们可以发现无论是哪种Shader,都是从左上角开始填充,然后利用Canvas去绘制具体某一区域(也就是说你canvas绘制的就是这相当于满屏的着色背景的一部分。)


我们可以通过Shader和Xfermode绘制出比较奇幻的效果,例如RadialGradient和Xfermode的SCREEN可以绘制灯光遮罩效果,还有支付宝的咻一咻,等着大家慢慢发掘。如果有好的idea可以留言给我。


源码下载地址

http://download.csdn.net/download/qian520ao/9786100


养成好的阅读习惯,没事多点点广告,活动下筋骨!



看完本文有收获?请分享给更多人


Java和Android架构

欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们。搜索微信公众号:JANiubility。

公众号:JANiubility