相关阅读:
吊炸天!74款APP完整源码!
谈谈我做技术面试官的经历--Android面试官给你的面试题和建议
Android自定义View - 最通俗易懂的自定义View原理系列
来源:http://blog.csdn.net/qian520ao
源码下载地址:见文末“阅读原文”
自定义view中画笔Paint有设置着色器方法paint.setShader(),我们来看一下这个Shader的子类
效果图
使用方式
启动雷达 | 关闭雷达 扫描
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)
从上图可以看出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]
三十角形
[凶残的德莱文]
LinearGradient [霓虹灯文字实战/图片倒影实战]
float x0 : 起始点渐变 x0 的坐标 float y0 : 起始点渐变 yo 的坐标
float x1 : 结束渐变点 x1 的坐标 float y1 : 结束渐变点 y1 的坐标
int color(),int color1 分别代表起始颜色和结束颜色,16进制的颜色 [0xAARRGGBB]
TileMode : 和bitmapShader一样都是CLAMP(拉伸)、MIRROR(镜像)、REPETA(重复)
另外的参数和SweepGradient参数作用是一样的。
不多说了,我们先上代码
结合图文我们可以很清晰的看出,我们从左上角到左下角着色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