码迷,mamicode.com
首页 > 移动开发 > 详细

Android自定义view 模仿win10进度条

时间:2021-01-01 12:29:07      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:duration   view   blog   就是   视图   off   技术干货   strong   png   

本文由zhangml0522投稿。

zhangml0522的博客地址:

http://blog.csdn.net/zhangml0522

先上预览图:

技术图片
流程

  • 1.一个匀速圆周运动的点

  • 2.多个匀速圆周运动的点

  • 3.多个圆周运动的点,速度由快到慢

  • 4.点与点之间的间距线性减少,动画的最后合为一个点

  • 5.为了让动画看起来更加流畅,需要在动画即将结束的时候手动绘制点

核心控件

  • PathMeasure:截取Path中的一部分并显示

  • ValueAnimator:完成动画从初始值平滑的过度到结束值的效果,同时还负责管理动画的播放次数、播放模式、以及对动画设置监听器等

1 一个匀速圆周运动的点

  1. 先用path画一个圆

  2. ValueAnimator设置为0f-1f的平滑

  3. 用PathMeasure根据ValueAnimator返回的值截取path上的一个点

private Paint mPaint;
private Path mPath;
private PathMeasure mPathMeasure;
private int mWidth,mHeight;
private ValueAnimator valueAnimator;
//用这个来接受ValueAnimator的返回值,代表整个动画的进度
private float t;


初始化画笔

![](https://s4.51cto.com/images/blog/202012/27/cc9424f3aae72bc5e53cfba1c836ab52.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
初始化Path和mPathMeasure 

这里角度不能选360,否则会测量失误,具体原因和android的内部优化有关

![](https://s4.51cto.com/images/blog/202012/27/e95e5c8911fdee56f96d95bb4223fddb.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
* 初始化ValueAnimator
![](https://s4.51cto.com/images/blog/202012/27/baca5707d5edd4d268d12aadb93fd47d.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
这里的ValueAnimator设置的是一个时长3秒的动画,再这3秒中,ValueAnimator会返回一个由0f-1f平滑的数字 
ValueAnimator.ofFloat(0f,1f).setDuration(3000) 
在这里我们用t来接受返回值,同时刷新视图

t = (float) animation.getAnimatedValue();
invalidate();

![](https://s4.51cto.com/images/blog/202012/27/00cba757d3fff463289c7f0257620bfe.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=) 
这里可以看出t的值,有0到1,这里就可以把t理解为我们这个动画的进度

* 开始绘制

![](https://s4.51cto.com/images/blog/202012/27/45ac6ef7f6e22c18254422fa92b7cd3f.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
* 结果图

![](https://s4.51cto.com/images/blog/202012/27/63e7e7df0b6611d034b6ae28ee5ed7a8.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
**2   多个匀速圆周运动的点**

我们设置让t每间隔0.05就画一个点,总共画4个点,注意这里getSegment()的最后一个要设置为true来保证画出来的是多个点而不是一条线

![](https://s4.51cto.com/images/blog/202012/27/7d009bb3c58b91131304a2f55dd0a0d9.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

结果图 

![](https://s4.51cto.com/images/blog/202012/27/ee3188c1e3632fd63c7f7ad5d838408c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

**3   速度由快到慢**

我们先绘制出路程-时间的函数图像 

![](https://s4.51cto.com/images/blog/202012/27/acbb0da516c071918fb931dbe5e6dca6.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
函数为y = -x*x + 2*x,当x=1时,y=mPathMeasure.getLength(); 
设s = mPathMeasure.getLength(); 
最终我们套用函数:y = -s*x*x+2*s*x; 
这里的Y轴代表的是path的长度,X轴对应时间 
所以把流程二中的y = s*x改成y = -s*x*x+2*s*x即可

![](https://s4.51cto.com/images/blog/202012/27/dfa7ac83c3b77bb2d5bc64898d5ae0a1.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

结果图 

![](https://s4.51cto.com/images/blog/202012/27/c7647043a6b6a4abb88068faf797f220.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)

**4   动画的最后合为一个点**

虽然流程3中点与点的间距已经开始减少,不过这只是因为速度不同间距才改变的,我们的目的是让这些点到最后合并为1个点,也就是说开始的时候每个点的X间距0.05,结束的时候要让他们的X相同 

目前点之间X的间距函数如下: 

![](https://s4.51cto.com/images/blog/202012/27/a3d70b1354328e5d2e240e368c045efd.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
我们最后要让当X=1时,他们的Y值相等,而且他们X的间距由0.05线性平滑到0
![](https://s4.51cto.com/images/blog/202012/27/ff5c54edecd222755b8e71dcea8fbe3b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
看函数图像已经很清楚了,修改后代码如下:

![](https://s4.51cto.com/images/blog/202012/27/1d511ce9e09567e75abc3163d08a6c09.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
结果图 

![](https://s4.51cto.com/images/blog/202012/27/3887d76a426dea8f5c171d1c1b5d2973.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
**5   完美的补刀**

这里已经完成了99.9%了,但细心的同学会发现,进度条每次转动一圈聚成一个点后都会闪一下,这是因为重新开始动画刷新视图的原因,这里的补救方法就是我们在动画快结束的时候手动画一个点

if(t>=0.95){
canvas.drawPoint(0,-150,mPaint);
}



这样我们就完成了这个进度条 

![](https://s4.51cto.com/images/blog/202012/27/37c9b2d2d626fad8e714bf7cf334b306.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
掘金是一个高质量的技术社区,从 RxJava 到 React Native,性能优化到优秀开源库,让你不错过 Android 开发的每一个技术干货。长按图片二维码识别或者各大应用市场搜索「掘金」,技术干货尽在掌握中。

![](https://s4.51cto.com/images/blog/202012/27/840046e4bfe0b57b06fe350e41312c8f.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
如果你有好的文章想和大家分享,欢迎投稿,直接向我投递文章链接即可。

欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号:

![](https://s4.51cto.com/images/blog/202012/27/ac0e0abbc3300d8e5dac2959d59c6a57.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
阅读原文

Android自定义view 模仿win10进度条

标签:duration   view   blog   就是   视图   off   技术干货   strong   png   

原文地址:https://blog.51cto.com/15064646/2575285

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!