android自定义view 模仿win10进度条

本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发。


PS:有朋友反映动画无法播放,那是因为PathMeasure.getLength()只在KITKAT以上版本有效,而对于以下版本一定要关闭硬件加速才有效。

先上预览图:

流程

  • 1.一个匀速圆周运动的点
  • 2.多个匀速圆周运动的点
  • 3.多个圆周运动的点,速度由快到慢
  • 4.点与点之间的间距线性减少,动画的最后合为一个点
  • 5.为了让动画看起来更加流畅,需要在动画即将结束的时候手动绘制点

核心控件

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

流程一

思路

  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;
  • 初始化画笔
    mPaint = new Paint();mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(15);mPaint.setColor(Color.WHITE);//设置画笔为园笔mPaint.setStrokeCap(Paint.Cap.ROUND);//抗锯齿mPaint.setAntiAlias(true);
  • 初始化Path和mPathMeasure
    这里角度不能选360,否则会测量失误,具体原因和android的内部优化有关
    mPath = new Path();RectF rect = new RectF(-150,-150,150,150);mPath.addArc(rect,-90,359.9f);mPathMeasure = new PathMeasure(mPath,false);
  • 初始化ValueAnimator
        valueAnimator = ValueAnimator.ofFloat(0f,1f).setDuration(3000);valueAnimator.setRepeatCount(-1);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {t = (float) animation.getAnimatedValue();invalidate();}});

这里的ValueAnimator设置的是一个时长3秒的动画,再这3秒中,ValueAnimator会返回一个由0f-1f平滑的数字
ValueAnimator.ofFloat(0f,1f).setDuration(3000)
在这里我们用t来接受返回值,同时刷新视图

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


这里可以看出t的值,有0到1,这里就可以把t理解为我们这个动画的进度

  • 开始绘制
    @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.translate(mWidth/2,mHeight/2);Path dst = new Path();mPathMeasure.getSegment(mPathMeasure.getLength()*t,mPathMeasure.getLength()*t+1,dst,true);canvas.drawPath(dst,mPaint);}
  • 结果图:

流程二

思路

  • 我们设置让t每间隔0.05就画一个点,总共画4个点,注意这里getSegment()的最后一个要设置为true来保证画出来的是多个点而不是一条线
    @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.translate(mWidth/2,mHeight/2);Path dst = new Path();int num = (int) (t/0.05);float s,y,x;switch(num){default:case 3:x = t-0.15f;s = mPathMeasure.getLength();y = s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 2:x = t-0.10f;s = mPathMeasure.getLength();y = s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 1:x = t-0.05f;s = mPathMeasure.getLength();y = s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 0:x = t;s = mPathMeasure.getLength();y = s*x;mPathMeasure.getSegment(y,y+1,dst,true);break;}canvas.drawPath(dst,mPaint);}
  • 结果图

流程三

思路

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

函数为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即可

switch(num){default:case 3:x = t-0.15f;s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 2:x = t-0.10f;s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 1:x = t-0.05f;s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 0:x = t;s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);break;}canvas.drawPath(dst,mPaint);
  • 结果图

流程四

思路

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

我们最后要让当X=1时,他们的Y值相等,而且他们X的间距由0.05线性平滑到0

看函数图像已经很清楚了,修改后代码如下:

        switch(num){default:case 3:x = t-0.15f*(1-t);s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 2:x = t-0.10f*(1-t);s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 1:x = t-0.05f*(1-t);s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 0:x = t;s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);break;}
  • 结果图

流程五

思路

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

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

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

最后这里附上源码:

package com.example.zhangml.view;import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;/*** Created by zhangml on 2016/9/12 0012.*/
public class Win8Search extends View{private Paint mPaint;private Path mPath;private PathMeasure mPathMeasure;private int mWidth,mHeight;private ValueAnimator valueAnimator;//用这个来接受ValueAnimator的返回值,代表整个动画的进度private float t;public Win8Search(Context context) {super(context);}public Win8Search(Context context, AttributeSet attrs) {super(context, attrs);init();valueAnimator.start();}private void init() {mPaint = new Paint();mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(15);mPaint.setColor(Color.WHITE);//设置画笔为园笔mPaint.setStrokeCap(Paint.Cap.ROUND);//抗锯齿mPaint.setAntiAlias(true);mPath = new Path();RectF rect = new RectF(-150,-150,150,150);mPath.addArc(rect,-90,359.9f);mPathMeasure = new PathMeasure(mPath,false);valueAnimator = ValueAnimator.ofFloat(0f,1f).setDuration(3000);valueAnimator.setRepeatCount(-1);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {t = (float) animation.getAnimatedValue();invalidate();}});}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.translate(mWidth/2,mHeight/2);Path dst = new Path();if(t>=0.95){canvas.drawPoint(0,-150,mPaint);}int num = (int) (t/0.05);float s,y,x;switch(num){default:case 3:x = t-0.15f*(1-t);s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 2:x = t-0.10f*(1-t);s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 1:x = t-0.05f*(1-t);s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);case 0:x = t;s = mPathMeasure.getLength();y = -s*x*x+2*s*x;mPathMeasure.getSegment(y,y+1,dst,true);break;}canvas.drawPath(dst,mPaint);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mWidth = w;mHeight = h;}}

android自定义view 模仿win10进度条相关推荐

  1. android自定义view圆环,Android自定义View实现圆环进度条

    本文实例为大家分享了android自定义view实现圆环进度条的具体代码,供大家参考,具体内容如下 效果展示 动画效果 view实现 1.底层圆环是灰色背景 2.上层圆环是红色背景 3.使用动画画一条 ...

  2. Android自定义view之圆形进度条

    本节介绍自定义view-圆形进度条 思路: 根据前面介绍的自定义view内容可拓展得之: 1:新建类继承自View 2:添加自定义view属性 3:重写onDraw(Canvas canvas) 4: ...

  3. android 自定义进度条 水量,Android自定义带水滴的进度条样式(带渐变色效果)...

    一.直接看效果 二.直接上代码 1.自定义控件部分 package com.susan.project.myapplication; import android.app.Activity; impo ...

  4. android 自定义view滚动条,Android自定义View实现等级滑动条的实例

    Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候 ...

  5. android 开发打赏布局,Android自定义View模仿虎扑直播界面的打赏按钮功能

    Android自定义View模仿虎扑直播界面的打赏按钮功能 发布时间:2020-09-28 12:15:53 来源:脚本之家 阅读:77 作者:shenhuniurou 前言 作为一个资深篮球爱好者, ...

  6. Android 自定义漂亮的圆形进度条

    公司有这样一个需求,实现这个圆弧进度条 所以,现在就将它抽取出来分享 如果需要是圆帽的就将,下面这句代码放开即可 mRingPaint.setStrokeCap(Paint.Cap.ROUND);// ...

  7. android自定义seekbar,Android自定义SeekBar实现视频播放进度条

    本文实例为大家分享了Android实现视频播放进度条的具体代码,供大家参考,具体内容如下 首先来看一下效果图,如下所示: 其中进度条如下: 接下来说一说我的思路,上面的进度拖动条有自定义的Thumb, ...

  8. Android自定义View系列之进度指示控件

    我开通微信公众号啦,如果大家喜欢我的文章,欢迎大家关注我的微信号,我会定期为大家推送Android中的热门知识. 今天为大家介绍另一个自定义View--进度指示器,这个在电商App和支付宝等中经常遇到 ...

  9. android自定义拱形,Android自定义View实现圆弧进度的效果

    前言 Android开发中,常常自定义View实现自己想要的效果,当然自定义View也是Android开发中比较难的部分,涉及到的知识有Canvas(画布),Paint(画笔)等,自定义控件分为三种: ...

最新文章

  1. springcloud 相同服务名_Spring 微服务从入门到入土
  2. python0.1+0.2不等于0.3_为什么0.1 + 0.2不等于0.3?
  3. QEMU-KVM中的多线程压缩迁移技术
  4. 独占锁、共享锁、更新锁,乐观锁、悲观锁
  5. Sparklens:Spark应用程序优化工具
  6. 需求迭代:迭代需求矩阵
  7. API生态的发展与机遇:从5000组数据看中国API生态与开发者现状
  8. 蛋壳公寓回应破产传闻:没有破产 也不会跑路
  9. webservice发布问题,部署iis后调用不成功
  10. Python 基础---列表
  11. Linux系统下配置JDK环境变量
  12. 二分--1043 - Triangle Partitioning
  13. 记录一次面试中的HTTP请求相关问题
  14. (vivo)安卓神器xposed框架Root安装指南
  15. 三分钟教你如何做好网站备案
  16. 计算机制图员主要学什么,制图员
  17. 服务器硬件配置及RAID配置操作
  18. 如何结交阿里P9,腾讯T4这样的大佬?
  19. 机器翻译古文也翻车?读了20次“苟富贵勿相忘”后,谷歌:没钱的人总会被遗忘...
  20. one to one

热门文章

  1. Physics物理引擎下载
  2. Firefly-RK3399 USB摄像头驱动及SimpleCV安装测试
  3. 数据可视化----ECharts---柱状图(三)
  4. python生成等差数列_python numpy函数中的linspace创建等差数列详解
  5. Parameter Sharing Exploration and Hetero-center Triplet Loss
  6. 【愚公系列】2022年10月 微信小程序-电商项目-微信支付后端功能实现(node版)
  7. 黑色简约多功能工具箱去水印外卖流量主小程序源码
  8. 合工大850参考书_合肥工业大学硕士目录
  9. 碳水循环饮食计算简介
  10. Vivado识别Flash型号失败