自定义动画(仿Win10加载动画)——优化
来源:互联网 发布:手机维修自学软件 编辑:程序博客网 时间:2024/06/05 19:18
此为前文章写的仿Win10加载动画的优化版
源代码
已更新到github
优化分析
一直觉得自己写的与原生的有差别,经过仔细对比观察,发现:
- 原生的圆点出发位置不是都在底部,而是第一个在底部,后面的紧接着前面一个,像球在管子里一样
- 圆点结束的位置就是该圆点开始的位置
- 经过比对,发现一个周期的时间是7500ms,非7000ms
经过优化后的对比:
优化后的时间校正图:
核心代码
不可否认,原生更加自然。为了自然,尝试了过去掉顶部的两段匀速运动,直接用四段三阶贝塞尔曲线,原理上是行的通的。但测试过N多参数,后来还是觉得不够自然,放弃了。最终还是选择原来的方法。
起始角度的计算
第一个圆点在最底部,第二个与第一个相差一个圆点对旋转中心所占的角度,后面也是圆点也是一样,与前一个圆点相差此角度。此角度可通过圆点半径与轨迹半径计算:
// 计算圆点对旋转中心所占的角度 float trackR = halfSize - dotR; dotDegree = (float) Math.toDegrees(2 * Math.asin(dotR / trackR));
参数与之前相比,有了很大调整(最主要的就是参数,调了无数遍才调出来……):
/** * 创建动画 * * @param view 需执行的控件 * @param index 该控件执行的顺序 * @return 该控件的动画 */private Animator createViewAnim(final View view, final int index) { long duration = 7500; // 一个周期(2圈)一共运行7500ms,固定值 // 最小执行单位时间 final float minRunUnit = duration / 100f; // 最小执行单位时间所占总时间的比例 double minRunPer = minRunUnit / duration; // 在插值器中实际值(Y坐标值),共8组 final double[] trueRunInOne = new double[]{ 0, 0, 160 / 720d, 190 / 720d, 360 / 720d, 520 / 720d, 550 / 720d, 1 }; // 动画开始的时间比偏移量。剩下的时间均摊到每个圆点上 final float offset = (float) (index * (100 - 86) * minRunPer / (mDotViews.length - 1)); // 在差值器中理论值(X坐标值),与realRunInOne对应 final double[] rawRunInOne = new double[]{ 0, offset + 0, offset + 11 * minRunPer, offset + 32 * minRunPer, offset + 43 * minRunPer, offset + 54 * minRunPer, offset + 75 * minRunPer, offset + 86 * minRunPer }; logI("minRunUnit=%f, minRunPer=%f, offset=%f", minRunUnit, minRunPer, offset); // 各贝塞尔曲线控制点的Y坐标 final float p1_2 = calculateLineY(rawRunInOne[2], trueRunInOne[2], rawRunInOne[3], trueRunInOne[3], rawRunInOne[1]); final float p1_4 = calculateLineY(rawRunInOne[2], trueRunInOne[2], rawRunInOne[3], trueRunInOne[3], rawRunInOne[4]); final float p1_5 = calculateLineY(rawRunInOne[5], trueRunInOne[5], rawRunInOne[6], trueRunInOne[6], rawRunInOne[4]); final float p1_7 = calculateLineY(rawRunInOne[5], trueRunInOne[5], rawRunInOne[6], trueRunInOne[6], rawRunInOne[7]); // A 创建属性动画:绕着中心点旋转2圈 ObjectAnimator objAnim = ObjectAnimator.ofFloat(view, "rotation", -dotDegree * index, 720 - dotDegree * index); // B 设置一个周期执行的时间 objAnim.setDuration(duration); // C 设置重复执行的次数:无限次重复执行下去 objAnim.setRepeatCount(ValueAnimator.INFINITE); // D 设置差值器 objAnim.setInterpolator(new TimeInterpolator() { @Override public float getInterpolation(float input) { if (input < rawRunInOne[1]) { // 1 等待开始 if (view.getVisibility() != INVISIBLE) { view.setVisibility(INVISIBLE); } return 0; } else if (input < rawRunInOne[2]) { if (view.getVisibility() != VISIBLE) { view.setVisibility(VISIBLE); } // 2 底部 → 左上角:贝赛尔曲线1 // 先转换成[0, 1]范围 input = calculateNewPercent(rawRunInOne[1], rawRunInOne[2], 0, 1, input); return calculateBezierQuadratic(trueRunInOne[1], p1_2, trueRunInOne[2], input); } else if (input < rawRunInOne[3]) { // 3 左上角 → 顶部:直线 return calculateLineY(rawRunInOne[2], trueRunInOne[2], rawRunInOne[3], trueRunInOne[3], input); } else if (input < rawRunInOne[4]) { // 4 顶部 → 底部:贝赛尔曲线2 input = calculateNewPercent(rawRunInOne[3], rawRunInOne[4], 0, 1, input); return calculateBezierQuadratic(trueRunInOne[3], p1_4, trueRunInOne[4], input); } else if (input < rawRunInOne[5]) { // 5 底部 → 左上角:贝赛尔曲线3 input = calculateNewPercent(rawRunInOne[4], rawRunInOne[5], 0, 1, input); return calculateBezierQuadratic(trueRunInOne[4], p1_5, trueRunInOne[5], input); } else if (input < rawRunInOne[6]) { // 6 左上角 → 顶部:直线 return calculateLineY(rawRunInOne[5], trueRunInOne[5], rawRunInOne[6], trueRunInOne[6], input); } else if (input < rawRunInOne[7]) { // 7 顶部 → 底部:贝赛尔曲线4 input = calculateNewPercent(rawRunInOne[6], rawRunInOne[7], 0, 1, input); return calculateBezierQuadratic(trueRunInOne[6], p1_7, trueRunInOne[7], input); } else { // 8 消失 if (view.getVisibility() != INVISIBLE) { view.setVisibility(INVISIBLE); } return 1; } } }); return objAnim;}
0 0
- 自定义动画(仿Win10加载动画)——优化
- 自定义动画(仿Win10加载动画)
- 自定义加载等待动画,仿金山词霸
- 自定义View——仿爱奇艺加载动画...
- Android开发——自定义加载动画
- APP实用开发—自定义加载动画
- Android绘图基础——仿华为加载动画
- 预加载动画(自定义)
- 自定义View(加载动画)
- Android自定义view-高仿小米视频加载动画效果
- Android仿百度加载动画
- WPF 仿windows8加载动画
- 高仿58加载动画
- 仿网易评论加载动画
- 仿雅虎视频加载动画
- qt qml仿win10 loading 动画
- 自定义View-仿Flipboard动画
- 优化加载gif动画
- 396. Rotate Function
- js/jquery常用方法(replaceALl、new Map()、点击th(表头)或拖动tr只前台排序)
- day35java基础
- 编写简单Hibernate步骤
- 终于!Linaro 加盟 Zephyr 项目
- 自定义动画(仿Win10加载动画)——优化
- SOAP Webservice和RESTful Webservice
- Android 中性能优化工具之TraceView使用总结
- 如何利用多核CPU来加速你的Linux命令 — awk, sed, bzip2, grep, wc等
- Linux常用命令
- PHP模拟登录并获取数据
- kubernetes二次开发(主要是开发满足自己业务的api)
- Notification 最简单的使用
- sip的几个概念