Android 鬼点子 - 如此 Q 弹
作者简介
本文由 Greenda米 原创并授权发布,未经原作者允许请勿转载。
依然是使用 Kotlin 实现的动画效果,希望大家会喜欢。
Greenda米 的博客地址:
http://www.jianshu.com/p/6e15f1e7edcb
在 uplabs 上看到一个设计师设计录音备忘录的设计。
动态图很惊艳:
自己尝试实现了一下,大约完成了50%的效果吧。
目前比较不满意的是背景气泡冒出时的粘连效果不是很理性。点击之后变成水滴向上移动的动画没有实现。另外,有的地方计算量比较大,没有优化,极少情况下出现卡顿。如果要真正运用到项目中的话,还需要继续优化。哦,对了没有实现 padding 啊什么的,还有颜色的变化都是直接写在了代码里面。
首先分析一下这个效果的各个部分。
有两坨重叠的,DuangDuang 的东西,第一层是纯色,第二层的半透明。
这两坨东西有一种蠕动的效果。
这两坨东西的大小是变化的。
时不时有气泡从背景冒出。
气泡冒出时有粘连效果。
对了,开始点击的时候有一种果冻的弹性效果。
然后完整代码如下:
下面我逐一介绍一下,每一种效果我是如何实现的。
1、有两坨重叠的,DuangDuang 的东西,第一层是纯色,第二层的半透明。
这个效果我使用的是六边形,然后过渡圆角实现的。DuangDuang 的效果是通过改变六边形每个角到圆心的距离实现蠕动的效果。为了这个效果更逼真,给这个六边形加上旋转的效果。第一层和第二层的效果是一样的,只是半径不同而已。
计算生成六边形顶点的方法是:
mPoints 存放计算后的顶点(6个),mRs 是每个顶点到圆心的半径,mRads 是每条半径的角度。
全局变量 mPoints 存放上层六边形的顶点,bPoints 存放背景六边形顶点。
在 onDrawa()
方法中调用了。
来更新六边形的顶点的数据。
我使用 sinX ,通过改变X的值,使 sinX 的值在 -1 和 +1 之间呈函数变化。当 X 是匀速变化时, sinX 是非匀速变化的。当角度是随机增加的时候,sinX 的变化就更是随机的。
这里是计算基础半径,整个六边形的放大和缩小的动画是在这里实现的,变化的范围是 -0.15 和 +0.15 之间。
实际的6个顶点的半径是在基础半径上计算的,变化范围是 -range~+range 的范围。
startRads 是当前半径的角度。用 半径 + 角度,计算出顶点的位置。
背景六边形的基础半径略大。
至此,1.2.3的效果就实现了。
2、然后是气泡冒出效果
在 private fun drawBubble(canvas: Canvas?) {}
方法中,是实现气泡效果的。
这里是产生一个气泡的过程。气泡的半径,发射的角度,发射的速度都是随机的。
distance 是当前气泡的距离圆心的距离。x , y 是气泡的圆心坐标。
这里是在计算气泡的半径(随着气泡飞出,半径减小),计算气泡的距离,计算坐标。
移除半径小于等于 0 的气泡。
这里根据计算后的结果画出气泡。后面就是粘连效果的实现。这里使用了贝塞尔曲线。
以一个小球为例:
it.x 和 it.y 是气泡的圆心坐标,width / 2 和 height / 2 是大圆的圆心坐标。大圆的半径 var mR = getRecentR()
,这里是找出 6 个半径中最短的。
AB 的距离是气泡的 distance , ∠ABE 是气泡的角度 it.rad ,代码中计算的th 是 ∠EBC , th2 是 ∠DBE 。角度知道了,半径也知道了,就可以算出4个切点的坐标了。
cx1 , cy2 就是第三个辅助点。点4 ,c1 和 点2,三个点构成一条贝塞尔曲线。点3 ,c2 和 点1,是另一条。
至此,粘连效果完成。
3、点击时有个模仿物理效果的放大缩小动画,果冻的弹性效果。
使用的是SpringAnimation,具体代码很简单,没使用过的老哥们可以看看之前的文章《Android 鬼点子-Q弹的计数器》。
推荐阅读