android 黑屏手势动画,Android MIUI 即刻APP 返回手势及动画 探索

8764c86c28ec

swipe_left.jpeg

8764c86c28ec

swipe_right.jpeg

18 年底做 Readhub APP 时就加入了这个返回动画效果。一直到现在,才有时间来简单总结和封装一下。

8764c86c28ec

swipeback.gif

不知道这个返回手势动画到底是 MIUI 还是「即刻」APP 首创,因为我那会儿还没用上 MIUI 全面屏。不过 MIUI 全面屏那个返回手势相对简单,固定位置。从这个效果上看,我觉得是 MIUI 先有这个效果,然后 「即刻」APP 优化丰富了一下。当然,可能还有另外一种情况,这是早就有的效果图,只是在目前,我已知有使用的就上面两个场景。

总结起来很简单,就是一个「贝塞尔曲线」的绘制,再外加一个箭头绘制。箭头什么的的绘制在之前的仓库中已经练习过很多。这次着重说说这个特殊图形需要怎么绘制。

对于贝塞尔曲线绘制,之前玩过两阶、三阶的。第一次看到这个效果,觉得贝塞尔曲能实现,但是这是几阶的,高阶的怎么玩,那就是从头开始。

在经过一番把玩探索后,最终确定这就是五阶的贝塞尔曲线, Android 似乎默认没有高阶对应的 api 。

8764c86c28ec

贝塞尔曲线.png

那这怎么办呢?曲线就是函数嘛,肯定有公式,网上就搜到公式写法。

private fun calculateY(i: Int, j: Int, t: Float): Float {

return if (i == 1) {

(1 - t) * controlPoints[j].y + t * controlPoints[j + 1].y

} else (1 - t) * calculateY(i - 1, j, t) + t * calculateY(i - 1, j + 1, t)

}

controlPoints 对应的就是那个五个控制点的集合。

addControlPoint(0, 0f, yResult - maxPeakValue * 1.5f)

addControlPoint(1, 0f, yResult - maxPeakValue * 1.5f * GOLDEN_RATIO)

addControlPoint(2, min, yResult)

addControlPoint(3, 0f, yResult + maxPeakValue * 1.5f * GOLDEN_RATIO)

addControlPoint(4, 0f, yResult + maxPeakValue * 1.5f)

接着就是控制是否拦截事件,我现在是做成 Helper 这种工具类型,和对应的 ViewGroup 是解耦的,其实就是 ViewDragHelper 的一个简单实现。

对了,最后考虑下来,实现了左右两边的滑动效果。至于上下,我觉得这种场景不大,就懒得去做了。

具体代码细节就不贴了,源码也没多少,这里讲遇到的一些细节问题或者写出来的 bug

返回退出应用后,后台程序预览中存在返回手势效果

这里其实就是一个先后问题,一开始是同步执行 invalidate() 和 onBackReleased() 。后来使用 Runnable + postDalay() 来延迟 onBackReleased() 执行。

贝塞尔曲线贴近屏幕的地方总有一个像素的白线

这里后面排查出来是我添加控制点,for 循环时角标是[0,length-1],最后一个没有添加计算到,所以计算出来的控制点就少了一个。最终效果就是绘制出来的图形 x 轴没有完全对称。偏差就在 1px 左右。

最后的效果就是总感觉下方有一跟白线。

for 循环处理好之后,发现右边绘制出来还是会有这个情况,具体原因不清楚,因为单看数据层面,它肯定是贴边的。最后很讨巧,使用到 translate() 将 Canvas 平移一个像素规避掉,这简直是程序员的小巧思,哈哈 🐶。

控制点数量及缓存

因为是用公式算的控制点,所以每一次绘制,其实简单理解就是讲一个一个点连接成一条曲线的。那么问题就是,点多,曲线当然最逼真,但是单位时间处理的数据量就上去了。

点少,可能你看到就是折线图了。

最后均衡在 50 个控制点,点与点之间的比例就是 2% 。在绘制等方法中肯定不能频繁创建对象,所以这 50 个点需要复用。

仓库地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值