精华内容
下载资源
问答
  • 1. 简介和效果分析一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以,...

    1. 简介和效果分析

    一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以,如果大家有什么意见或者建议可以给我留言,望斧正。先看一下效果图吧。这个view有两种状态,一是成功的状态,打上一个大勾,另外一个就是失败的状态,会显示一个红叉表示失败。

    54bb8fcc4f5679c9f645a50799bfa463.gif

    这个是下载或者说加载成功的动画可以看到外圈有一个片进度加载过程,每转一小圈就是加载成功一部分(在这里我是把100%的进度分为了10次,也就是说如果成功应该是转了十圈的),圆圈的中间会掉下一个小圆(强行是一个水滴。。),然后水涨船高,就加载成功了。然后再看一下加载失败的图。

    5d6afbefdfad07bfcaeebaaef6d2a06b.gif

    加载的前部分就不说了,不同的就是在加载过程中如果失败的话就是打叉。效果我们也看完了,来看看怎么实现的吧。我们按过程来拆解。

    2. 实现过程

    外圈背景和进度弧的绘制

    e05cb7e98dd076e671a57f2cf641cd90.gif

    2.1 先看背景圆圈吧

    colorArc = Color.argb(255, 0, 150, 136);
    colorsoild = Color.argb(255, 173, 216, 230);
    colorFork = Color.argb(255, 238, 0, 0);
    
    arcPaint = new Paint();
    arcPaint.setAntiAlias(true);
    arcPaint.setColor(colorArc);
    arcPaint.setStrokeWidth(strokeWidth);
    arcPaint.setStyle(Paint.Style.STROKE);
    
    circlePaint = new Paint(arcPaint);
    circlePaint.setColor(colorsoild);

    我们先是定义了paint,那是必须的,然后初始化,然后就在ondraw里面进行绘制了。不过还有一个重要的东西,就是圆弧的动态的啊,那是怎么做的呢,我在这是使用了属性动画,我们来看:

    //圆圈旋转动画
            mRotateAnimation = ValueAnimator.ofFloat(0f, 1f);
            mRotateAnimation.setDuration(2000);
            mRotateAnimation.setRepeatCount(100);
            mRotateAnimation.setStartDelay(0);
            mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
            mRotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    percent = (float) animation.getAnimatedValue();
                    downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);
     
                    if (downLength / waveHeight > 1.01) {
                        if (currentProgress < maxProgress) {
                            if (isRise) {
                                currentProgress += 10;
                                isRise = false;
                            }
                        } else {
                            if ((float) animation.getAnimatedValue() > 0.99)
                                mRotateAnimation.cancel();
                        }
                    } else {
                        isRise = true;
                    }
                    invalidate();
                }
            });

    我们先在只用看percent这个参数就行了,也就是说通过属性动画不停的改变percent的值来进行动态的绘制。改变值之后我们调用invalidate这个方法,让ondraw不断调用。然后就是绘制了,我们来看ondraw里的这两行:

    canvas.drawArc(rectF, 0, 360, false, circlePaint);
    canvas.drawArc(rectF, -90 - 360 * percent, -(20 + percent * 344), false, arcPaint);

    这里的restF是一个绘制区域,就是定义的两个图形绘制的区域可以看到,先是绘制了一个圆圈,然后重点是后面这行,percent不断改变,圆弧两个顶点的绘制起始和快慢是不一样的,然后重点都是 - 90度方向,也就有了加载一圈的效果。

    2.2 水波上升的效果

    65d04da105ba4de38dcbbc02dd6c73b0.gif

    在讲水波绘制之前,先简单了解一下贝塞尔曲线和使用,在path的方法中有一个这样的方法,quadTo:

    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
            isSimplePath = false;
            native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
        }

    四个参数分别是中间点和终点的坐标值。没图说个**,那我们来看一个图

    7bbf8111c7b44f9a72c0afcbdffd120b.gif

    现在我们可以看到通过三个点和绘制的过程,这个方法可以绘制出如图的红色线(二阶贝塞尔曲线),通过这样我们就可以绘制一条类似于正弦的上下震动的波浪线了。

    还有一个就是绘制的时候我重新建了一块画布,然后画出底部圆形上面波浪的图形,怎么绘制呢,用到了这个属性

    //交集上层
    progressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    也就是去绘制两个图像的上面部分,相信大家应该了解,如果不了解的话可以去搜索一下,这里就不介绍了。然后绘制曲线。

    //波的数量
                int count = (int) ((int) (bitmapWidth / 2 + 1) * 2 / space);
     
                //决定上升的高度
                waveHeight = (1 - (float) currentProgress / maxProgress) * bitmapHeight;
                path.moveTo(-bitmapWidth + waveHeight, waveHeight);
                //决定 曲线的弯曲程度
                float d = (1 - (float) currentProgress / maxProgress) * space;
                for (int i = 0; i < count; i++) {
                    path.rQuadTo(space, -d, space * 2, 0);
                    path.rQuadTo(space, d, space * 2, 0);
                }

    先把起点移动移动到我们计算好的点,这里的space是一个我自己定的值,可以更改,这里的moveTo相当于先移动到上图的P0点,这里的rQuadToQuadTo的区别就是前者是相对起点的坐标,而不是相对整个画布的坐标,然后通过rQuadTo绘制第二个点也就是P1点,同理P2,现在的效果差不多就是这样的,图中参数对应变量意义。

    3a624a593fe50d3d5ef83105d4cea09c.png

    然后不断循环这个过程知道把计算的count数量的整个波画完

    3. 小球下落(强行是水滴 0.0)

    水滴一直下落,所以要计算下落的距离

    private float downLength;
    downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);

    这里下落的时候我当做和水上升当做同步上升了,后面才发现这样并不好,但是这里水下落的最大长达是固定的,怎么样才能在水滴下落到水面的时候就让水面上升呢? 那就要看一下下面这几行代码了

    if (downLength / waveHeight > 1.01) {
          if (currentProgress < maxProgress) {
             if (isRise) {
                  currentProgress += 10;
                  isRise = false;
             }
         } else {
            if ((float) animation.getAnimatedValue() > 0.99)
               mRotateAnimation.cancel();
            }
      } else {
          isRise = true;
    }

    如在水滴下落的距离和水面上升到的距离作比较,如果基本是同一个位置的话,直接控制水波上升,然后水波进入下一个上升等待状态。

    4. 动画打勾(如果是成功的结果)

    首先,打勾需要一个路径,这里路径我们可以自己定义,

    tickPath = new Path();
            tickPath.moveTo(width / 2 - 0.5f * radius, height / 2);
            tickPath.lineTo(width / 2 - 0.5f * radius + 0.4f * radius, height / 2 + 0.3f * radius);
            tickPath.lineTo(width / 2 - 0.5f * radius + radius, height / 2 - 0.3f * radius);
            tickMeasure = new PathMeasure(tickPath, false);

    这里的代码就不过所解释了,然后就是我们的绘制过程了,我还是使用的属性动画来动态改变绘制的过程中的值。

    //打钩动画
            tickAnimation = ValueAnimator.ofFloat(0f, 1f);
            tickAnimation.setStartDelay(200);
            tickAnimation.setDuration(500);
            tickAnimation.setInterpolator(new AccelerateInterpolator());
            tickAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    tickPercent = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });

    然后动态绘制的过程,这里又用到了PathMeasure,不太懂得同学可以去搜索了解一下

    canvas.drawArc(rectF, 0, 360, false, solidCirclePaint);
                canvas.drawArc(rectF, 0, 360, false, arcPaint);
                Path path = new Path();
                tickMeasure.getSegment(0, tickPercent * tickMeasure.getLength(), path, true);
                path.rLineTo(0, 0);
                canvas.drawPath(path, arcPaint);

    效果就是这样的了

    5cdef02ffc1108580fd71b2b48eb70f0.gif

    5.红叉的绘制

    红叉的绘制就和勾的绘制其实是一样的,这里就不分析了。感兴趣的同学可以去看代码。

    这里给上代码下载地址,欢迎大家查看并给个star。源码地址:https://github.com/XIONG1203/DownloadProgressView

    阿里P6P7【安卓】进阶资料分享+加薪跳槽必备面试题+安卓程序员简历模板shimo.im
    8428ebfc870e43a131141445802f80e5.png

    15G的Android架构进阶、视频资料及安卓程序员简历模板,需要的同学自取;

    大家可以关注专栏,每天都有优质文章分享

    Android开发架构zhuanlan.zhihu.com
    fcab4762e42456f10a97b634588096fc.png
    展开全文
  • 本文作者:BIGPiePieTree,文章地址:http://mrw.so/53GGhc1. 简介和效果分析一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠...

    1d907e51ad06e7e96d0461a10f42196b.png

    本文作者:BIGPiePieTree,文章地址:http://mrw.so/53GGhc

    1. 简介和效果分析

    一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以,如果大家有什么意见或者建议可以给我留言,望斧正。先看一下效果图吧。这个view有两种状态,一是成功的状态,打上一个大勾,另外一个就是失败的状态,会显示一个红叉表示失败。

    c775f044fd68253b67906487f39c7f5b.gif

    这个是下载或者说加载成功的动画可以看到外圈有一个片进度加载过程,每转一小圈就是加载成功一部分(在这里我是把100%的进度分为了10次,也就是说如果成功应该是转了十圈的),圆圈的中间会掉下一个小圆(强行是一个水滴。。),然后水涨船高,就加载成功了。然后再看一下加载失败的图。

    561560b8b8f23f8f2ba8fbb1bed6b41b.gif

    加载的前部分就不说了,不同的就是在加载过程中如果失败的话就是打叉。效果我们也看完了,来看看怎么实现的吧。我们按过程来拆解。

    2. 实现过程

    外圈背景和进度弧的绘制

    962c310c85fc46145eb65bc8915e77ec.gif
    2.1 先看背景圆圈吧
    colorArc = Color.argb(255, 0, 150, 136);
    colorsoild = Color.argb(255, 173, 216, 230);
    colorFork = Color.argb(255, 238, 0, 0);

    arcPaint = new Paint();
    arcPaint.setAntiAlias(true);
    arcPaint.setColor(colorArc);
    arcPaint.setStrokeWidth(strokeWidth);
    arcPaint.setStyle(Paint.Style.STROKE);

    circlePaint = new Paint(arcPaint);
    circlePaint.setColor(colorsoild);

    我们先是定义了paint,那是必须的,然后初始化,然后就在ondraw里面进行绘制了。不过还有一个重要的东西,就是圆弧的动态的啊,那是怎么做的呢,我在这是使用了属性动画,我们来看:

            //圆圈旋转动画
    mRotateAnimation = ValueAnimator.ofFloat(0f, 1f);
    mRotateAnimation.setDuration(2000);
    mRotateAnimation.setRepeatCount(100);
    mRotateAnimation.setStartDelay(0);
    mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
    mRotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    percent = (float) animation.getAnimatedValue();
    downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);

    if (downLength / waveHeight > 1.01) {
    if (currentProgress < maxProgress) {
    if (isRise) {
    currentProgress += 10;
    isRise = false;
    }
    } else {
    if ((float) animation.getAnimatedValue() > 0.99)
    mRotateAnimation.cancel();
    }
    } else {
    isRise = true;
    }
    invalidate();
    }
    });

    我们先在只用看percent这个参数就行了,也就是说通过属性动画不停的改变percent的值来进行动态的绘制。改变值之后我们调用invalidate这个方法,让ondraw不断调用。然后就是绘制了,我们来看ondraw里的这两行:

    canvas.drawArc(rectF, 0, 360, false, circlePaint);
    canvas.drawArc(rectF, -90 - 360 * percent, -(20 + percent * 344), false, arcPaint);

    这里的restF是一个绘制区域,就是定义的两个图形绘制的区域可以看到,先是绘制了一个圆圈,然后重点是后面这行,percent不断改变,圆弧两个顶点的绘制起始和快慢是不一样的,然后重点都是 - 90度方向,也就有了加载一圈的效果。

    2.2 水波上升的效果
    adb34e296c86cd210ce07b67a1254199.gif

    在讲水波绘制之前,先简单了解一下贝塞尔曲线和使用,在path的方法中有一个这样的方法,quadTo:

        public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
    isSimplePath = false;
    native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
    }

    四个参数分别是中间点和终点的坐标值。没图说个**,那我们来看一个图

    557a69a7a306f3ded4d6ec443f74f610.gif

    现在我们可以看到通过三个点和绘制的过程,这个方法可以绘制出如图的红色线(二阶贝塞尔曲线),通过这样我们就可以绘制一条类似于正弦的上下震动的波浪线了。

    还有一个就是绘制的时候我重新建了一块画布,然后画出底部圆形上面波浪的图形,怎么绘制呢,用到了这个属性

    //交集上层
    progressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    也就是去绘制两个图像的上面部分,相信大家应该了解,如果不了解的话可以去搜索一下,这里就不介绍了。然后绘制曲线。

                //波的数量
    int count = (int) ((int) (bitmapWidth / 2 + 1) * 2 / space);

    //决定上升的高度
    waveHeight = (1 - (float) currentProgress / maxProgress) * bitmapHeight;
    path.moveTo(-bitmapWidth + waveHeight, waveHeight);
    //决定 曲线的弯曲程度
    float d = (1 - (float) currentProgress / maxProgress) * space;
    for (int i = 0; i < count; i++) {
    path.rQuadTo(space, -d, space * 2, 0);
    path.rQuadTo(space, d, space * 2, 0);
    }

    先把起点移动移动到我们计算好的点,这里的space是一个我自己定的值,可以更改,这里的moveTo相当于先移动到上图的P0点,这里的rQuadToQuadTo的区别就是前者是相对起点的坐标,而不是相对整个画布的坐标,然后通过rQuadTo绘制第二个点也就是P1点,同理P2,现在的效果差不多就是这样的,图中参数对应变量意义。

    04623ad928202797a0c26954be209c9e.png

    然后不断循环这个过程知道把计算的count数量的整个波画完

    3. 小球下落(强行是水滴 0.0)

    水滴一直下落,所以要计算下落的距离

    private float downLength;
    downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);

    这里下落的时候我当做和水上升当做同步上升了,后面才发现这样并不好,但是这里水下落的最大长达是固定的,怎么样才能在水滴下落到水面的时候就让水面上升呢? 那就要看一下下面这几行代码了

    if (downLength / waveHeight > 1.01) {
    if (currentProgress < maxProgress) {
    if (isRise) {
    currentProgress += 10;
    isRise = false;
    }
    } else {
    if ((float) animation.getAnimatedValue() > 0.99)
    mRotateAnimation.cancel();
    }
    } else {
    isRise = true;
    }

    如在水滴下落的距离和水面上升到的距离作比较,如果基本是同一个位置的话,直接控制水波上升,然后水波进入下一个上升等待状态。

    4. 动画打勾(如果是成功的结果)

    首先,打勾需要一个路径,这里路径我们可以自己定义,

            tickPath = new Path();
    tickPath.moveTo(width / 2 - 0.5f * radius, height / 2);
    tickPath.lineTo(width / 2 - 0.5f * radius + 0.4f * radius, height / 2 + 0.3f * radius);
    tickPath.lineTo(width / 2 - 0.5f * radius + radius, height / 2 - 0.3f * radius);
    tickMeasure = new PathMeasure(tickPath, false);

    这里的代码就不过所解释了,然后就是我们的绘制过程了,我还是使用的属性动画来动态改变绘制的过程中的值。

            //打钩动画
    tickAnimation = ValueAnimator.ofFloat(0f, 1f);
    tickAnimation.setStartDelay(200);
    tickAnimation.setDuration(500);
    tickAnimation.setInterpolator(new AccelerateInterpolator());
    tickAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    tickPercent = (float) animation.getAnimatedValue();
    invalidate();
    }
    });

    然后动态绘制的过程,这里又用到了PathMeasure,不太懂得同学可以去搜索了解一下

                canvas.drawArc(rectF, 0, 360, false, solidCirclePaint);
    canvas.drawArc(rectF, 0, 360, false, arcPaint);
    Path path = new Path();
    tickMeasure.getSegment(0, tickPercent * tickMeasure.getLength(), path, true);
    path.rLineTo(0, 0);
    canvas.drawPath(path, arcPaint);

    效果就是这样的了

    4b245d6b2b1f13b3715cd53c79897bfe.gif
    5.红叉的绘制

    红叉的绘制就和勾的绘制其实是一样的,这里就不分析了。感兴趣的同学可以去看代码。

    这里给上代码下载地址,欢迎大家查看并给个star。源码地址:https://github.com/XIONG1203/DownloadProgressView

    以上就是本文全部内容,喜欢❤️的话就转发一下、点个在看支持一下吧!

    ---END---

    推荐阅读:
    一文彻底搞懂Kotlin中的委托
    Flutter 玩转微信——闪屏页妙用
    RecyclerView双列表联动
    Java线程池使用与分析总结
    fd8793f5b038af30432046c35fca74de.png每一个“在看”,我都当成真的喜欢69c1caec90b779368cd7d2e874675171.gif
    展开全文
  • 波浪过程下载Loading动画

    千次阅读 2016-12-04 11:31:14
    Loading 动画  一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以。先...

    下载Loading 动画

    一,简介和效果分析

           一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以,如果大家有什么意见或者建议可以给我留言,望斧正。先看一下效果图吧。这个view有两种状态,一是成功的状态,打上一个大勾,另外一个就是失败的状态,会显示一个红叉表示失败。

                        


    这个是下载或者说加载成功的动画可以看到外圈有一个片进度加载过程,每转一小圈就是加载成功一部分(在这里我是把100%的进度分为了10次,也就是说如果成功应该是转了十圈的),圆圈的中间会掉下一个小圆(强行是一个水滴。。),然后水涨船高,就加载成功了。然后再看一下加载失败的图。
     
                        
    加载的前部分就不说了,不同的就是在加载过程中如果失败的话就是打叉。效果我们也看完了,来看看怎么实现的吧。我们按过程来拆解。

    二,实现过程

    1.  外圈背景和进度弧的绘制
                          


      先看背景圆圈吧,
              colorArc = Color.argb(255, 0, 150, 136);
              colorsoild = Color.argb(255, 173, 216, 230);
              colorFork = Color.argb(255, 238, 0, 0);
      
              arcPaint = new Paint();
              arcPaint.setAntiAlias(true);
              arcPaint.setColor(colorArc);
              arcPaint.setStrokeWidth(strokeWidth);
              arcPaint.setStyle(Paint.Style.STROKE);
      
              circlePaint = new Paint(arcPaint);
              circlePaint.setColor(colorsoild);

      我们先是定义了paint,那是必须的,然后初始化,然后就在ondraw里面进行绘制了。不过还有一个重要的东西,就是圆弧的动态的啊,那是怎么做的呢,我在这是使用了属性动画,我们来看
              //圆圈旋转动画
              mRotateAnimation = ValueAnimator.ofFloat(0f, 1f);
              mRotateAnimation.setDuration(2000);
              mRotateAnimation.setRepeatCount(100);
              mRotateAnimation.setStartDelay(0);
              mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
              mRotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                  @Override
                  public void onAnimationUpdate(ValueAnimator animation) {
                      percent = (float) animation.getAnimatedValue();
                      downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);
      
                      if (downLength / waveHeight > 1.01) {
                          if (currentProgress < maxProgress) {
                              if (isRise) {
                                  currentProgress += 10;
                                  isRise = false;
                              }
                          } else {
                              if ((float) animation.getAnimatedValue() > 0.99)
                                  mRotateAnimation.cancel();
                          }
                      } else {
                          isRise = true;
                      }
                      invalidate();
                  }
              });
      我们先在只用看percent这个参数就行了,也就是说通过属性动画不停的改变percent的值来进行动态的绘制。改变值之后我们调用invalidate这个方法,让ondraw不断调用。然后就是绘制了,我们来看ondraw里的这两行,
                  canvas.drawArc(rectF, 0, 360, false, circlePaint);
                  canvas.drawArc(rectF, -90 - 360 * percent, -(20 + percent * 344), false, arcPaint);

      这里的restF是一个绘制区域,就是定义的两个图形绘制的区域可以看到,先是绘制了一个圆圈,然后重点是后面这行,percent不断改变,圆弧两个顶点的绘制起始和快慢是不一样的,然后重点都是 - 90度方向,也就有了加载一圈的效果。
    2. 水波上升的效果

                         
      在讲水波绘制之前,先简单了解一下贝塞尔曲线和使用,在path的方法中有一个这样的方法,quadTo
          public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
              isSimplePath = false;
              native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
          }
      
      
      四个参数分别是中间点和终点的坐标值。没图说个**,那我们来看一个图
         

      现在我们可以看到通过三个点和绘制的过程,这个方法可以绘制出如图的红色线(二阶贝塞尔曲线),通过这样我们就可以绘制一条类似于正弦的上下震动的波浪线了。
      还有一个就是绘制的时候我重新建了一块画布,然后画出底部圆形上面波浪的图形,怎么绘制呢,用到了这个属性,
              //交集上层
              progressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
      
      
      也就是去绘制两个图像的上面部分,相信大家应该了解,如果不了解的话可以去搜索一下,这里就不介绍了。然后绘制曲线。
                  //波的数量
                  int count = (int) ((int) (bitmapWidth / 2 + 1) * 2 / space);
      
                  //决定上升的高度
                  waveHeight = (1 - (float) currentProgress / maxProgress) * bitmapHeight;
                  path.moveTo(-bitmapWidth + waveHeight, waveHeight);
                  //决定 曲线的弯曲程度
                  float d = (1 - (float) currentProgress / maxProgress) * space;
                  for (int i = 0; i < count; i++) {
                      path.rQuadTo(space, -d, space * 2, 0);
                      path.rQuadTo(space, d, space * 2, 0);
                  }
      
      
      先把起点移动移动到我们计算好的点,这里的space是一个我自己定的值,可以更改,这里的moveTo相当于先移动到上图的P0点,这里的rQuadTo和QuadTo的区别就是前者是相对起点的坐标,而不是相对整个画布的坐标,然后通过rQuadTo绘制第二个点也就是P1点,同理P2.现在的效果差不多就是这样的,图中参数对应变量意义。

      然后不断循环这个过程知道把计算的count数量的整个波画完。
    3. 小球下落(强行是水滴 0.0)
      水滴一直下落,所以要计算下落的距离,
      private float downLength;
      downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);
      

      这里下落的时候我当做和水上升当做同步上升了,后面才发现这样并不好,但是这里水下落的最大长达是固定的,怎么样才能在水滴下落到水面的时候就让水面上升呢?  那就要看一下下面这几行代码了,
      if (downLength / waveHeight > 1.01) {
                          if (currentProgress < maxProgress) {
                              if (isRise) {
                                  currentProgress += 10;
                                  isRise = false;
                              }
                          } else {
                              if ((float) animation.getAnimatedValue() > 0.99)
                                  mRotateAnimation.cancel();
                          }
                      } else {
                          isRise = true;
                      }
      如在水滴下落的距离和水面上升到的距离作比较,如果基本是同一个位置的话,直接控制水波上升,然后水波进入下一个上升等待状态。
    4. 动画打勾(如果是成功的结果)
      首先,打勾需要一个路径,这里路径我们可以自己定义,
              tickPath = new Path();
              tickPath.moveTo(width / 2 - 0.5f * radius, height / 2);
              tickPath.lineTo(width / 2 - 0.5f * radius + 0.4f * radius, height / 2 + 0.3f * radius);
              tickPath.lineTo(width / 2 - 0.5f * radius + radius, height / 2 - 0.3f * radius);
              tickMeasure = new PathMeasure(tickPath, false);
      这里的代码就不过所解释了,
      然后就是我们的绘制过程了,我还是使用的属性动画来动态改变绘制的过程中的值。
              //打钩动画
              tickAnimation = ValueAnimator.ofFloat(0f, 1f);
              tickAnimation.setStartDelay(200);
              tickAnimation.setDuration(500);
              tickAnimation.setInterpolator(new AccelerateInterpolator());
              tickAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                  @Override
                  public void onAnimationUpdate(ValueAnimator animation) {
                      tickPercent = (float) animation.getAnimatedValue();
                      invalidate();
                  }
              });
      然后动态绘制的过程,这里又用到了PathMeasure,不太懂得同学可以去搜索了解一下,
                  canvas.drawArc(rectF, 0, 360, false, solidCirclePaint);
                  canvas.drawArc(rectF, 0, 360, false, arcPaint);
                  Path path = new Path();
                  tickMeasure.getSegment(0, tickPercent * tickMeasure.getLength(), path, true);
                  path.rLineTo(0, 0);
                  canvas.drawPath(path, arcPaint);
      效果就是这样的了
                         
    5. 红叉的绘制
      红叉的绘制就和勾的绘制其实是一样的,这里就不分析了。感兴趣的同学可以去看代码。

      这里给上代码下载地址,欢迎大家查看并给个star。
      GITHUB源码下载


    展开全文
  • JavaScript的精典案例,对学习者有很好帮助
  • 1. 简介和效果分析一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以,...

    1. 简介和效果分析

    一直都觉得有很多loading动画挺炫酷的,然后自己看过一些之后也想实现一个,加强一下对绘制view的练习,能力有限,很多地方的实现的有欠考虑和逻辑优化,不管怎么样画了两天还是把效果做的还可以,如果大家有什么意见或者建议可以给我留言,望斧正。先看一下效果图吧。这个view有两种状态,一是成功的状态,打上一个大勾,另外一个就是失败的状态,会显示一个红叉表示失败。

    这个是下载或者说加载成功的动画可以看到外圈有一个片进度加载过程,每转一小圈就是加载成功一部分(在这里我是把100%的进度分为了10次,也就是说如果成功应该是转了十圈的),圆圈的中间会掉下一个小圆(强行是一个水滴。。),然后水涨船高,就加载成功了。然后再看一下加载失败的图。

    加载的前部分就不说了,不同的就是在加载过程中如果失败的话就是打叉。效果我们也看完了,来看看怎么实现的吧。我们按过程来拆解。

    2. 实现过程

    外圈背景和进度弧的绘制

    2.1 先看背景圆圈吧

    colorArc = Color.argb(255, 0, 150, 136);

    colorsoild = Color.argb(255, 173, 216, 230);

    colorFork = Color.argb(255, 238, 0, 0);

    arcPaint = new Paint();

    arcPaint.setAntiAlias(true);

    arcPaint.setColor(colorArc);

    arcPaint.setStrokeWidth(strokeWidth);

    arcPaint.setStyle(Paint.Style.STROKE);

    circlePaint = new Paint(arcPaint);

    circlePaint.setColor(colorsoild);

    我们先是定义了paint,那是必须的,然后初始化,然后就在ondraw里面进行绘制了。不过还有一个重要的东西,就是圆弧的动态的啊,那是怎么做的呢,我在这是使用了属性动画,我们来看:

    //圆圈旋转动画

    mRotateAnimation = ValueAnimator.ofFloat(0f, 1f);

    mRotateAnimation.setDuration(2000);

    mRotateAnimation.setRepeatCount(100);

    mRotateAnimation.setStartDelay(0);

    mRotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());

    mRotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override

    public void onAnimationUpdate(ValueAnimator animation) {

    percent = (float) animation.getAnimatedValue();

    downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);

    if (downLength / waveHeight > 1.01) {

    if (currentProgress < maxProgress) {

    if (isRise) {

    currentProgress += 10;

    isRise = false;

    }

    } else {

    if ((float) animation.getAnimatedValue() > 0.99)

    mRotateAnimation.cancel();

    }

    } else {

    isRise = true;

    }

    invalidate();

    }

    });

    我们先在只用看percent这个参数就行了,也就是说通过属性动画不停的改变percent的值来进行动态的绘制。改变值之后我们调用invalidate这个方法,让ondraw不断调用。然后就是绘制了,我们来看ondraw里的这两行:

    canvas.drawArc(rectF, 0, 360, false, circlePaint);

    canvas.drawArc(rectF, -90 - 360 * percent, -(20 + percent * 344), false, arcPaint);

    这里的restF是一个绘制区域,就是定义的两个图形绘制的区域可以看到,先是绘制了一个圆圈,然后重点是后面这行,percent不断改变,圆弧两个顶点的绘制起始和快慢是不一样的,然后重点都是 - 90度方向,也就有了加载一圈的效果。

    2.2 水波上升的效果

    在讲水波绘制之前,先简单了解一下贝塞尔曲线和使用,在path的方法中有一个这样的方法,quadTo:

    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {

    isSimplePath = false;

    native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);

    }

    四个参数分别是中间点和终点的坐标值。没图说个**,那我们来看一个图

    现在我们可以看到通过三个点和绘制的过程,这个方法可以绘制出如图的红色线(二阶贝塞尔曲线),通过这样我们就可以绘制一条类似于正弦的上下震动的波浪线了。

    还有一个就是绘制的时候我重新建了一块画布,然后画出底部圆形上面波浪的图形,怎么绘制呢,用到了这个属性

    //交集上层

    progressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    也就是去绘制两个图像的上面部分,相信大家应该了解,如果不了解的话可以去搜索一下,这里就不介绍了。然后绘制曲线。

    //波的数量

    int count = (int) ((int) (bitmapWidth / 2 + 1) * 2 / space);

    //决定上升的高度

    waveHeight = (1 - (float) currentProgress / maxProgress) * bitmapHeight;

    path.moveTo(-bitmapWidth + waveHeight, waveHeight);

    //决定 曲线的弯曲程度

    float d = (1 - (float) currentProgress / maxProgress) * space;

    for (int i = 0; i < count; i++) {

    path.rQuadTo(space, -d, space * 2, 0);

    path.rQuadTo(space, d, space * 2, 0);

    }

    先把起点移动移动到我们计算好的点,这里的space是一个我自己定的值,可以更改,这里的moveTo相当于先移动到上图的P0点,这里的rQuadTo和QuadTo的区别就是前者是相对起点的坐标,而不是相对整个画布的坐标,然后通过rQuadTo绘制第二个点也就是P1点,同理P2,现在的效果差不多就是这样的,图中参数对应变量意义。

    然后不断循环这个过程知道把计算的count数量的整个波画完

    3. 小球下落(强行是水滴 0.0)

    水滴一直下落,所以要计算下落的距离

    private float downLength;

    downLength = (float) animation.getAnimatedValue() * (2f * radius + 2 * dotRadius);

    这里下落的时候我当做和水上升当做同步上升了,后面才发现这样并不好,但是这里水下落的最大长达是固定的,怎么样才能在水滴下落到水面的时候就让水面上升呢? 那就要看一下下面这几行代码了

    if (downLength / waveHeight > 1.01) {

    if (currentProgress < maxProgress) {

    if (isRise) {

    currentProgress += 10;

    isRise = false;

    }

    } else {

    if ((float) animation.getAnimatedValue() > 0.99)

    mRotateAnimation.cancel();

    }

    } else {

    isRise = true;

    }

    如在水滴下落的距离和水面上升到的距离作比较,如果基本是同一个位置的话,直接控制水波上升,然后水波进入下一个上升等待状态。

    4. 动画打勾(如果是成功的结果)

    首先,打勾需要一个路径,这里路径我们可以自己定义,

    tickPath = new Path();

    tickPath.moveTo(width / 2 - 0.5f * radius, height / 2);

    tickPath.lineTo(width / 2 - 0.5f * radius + 0.4f * radius, height / 2 + 0.3f * radius);

    tickPath.lineTo(width / 2 - 0.5f * radius + radius, height / 2 - 0.3f * radius);

    tickMeasure = new PathMeasure(tickPath, false);

    这里的代码就不过所解释了,然后就是我们的绘制过程了,我还是使用的属性动画来动态改变绘制的过程中的值。

    //打钩动画

    tickAnimation = ValueAnimator.ofFloat(0f, 1f);

    tickAnimation.setStartDelay(200);

    tickAnimation.setDuration(500);

    tickAnimation.setInterpolator(new AccelerateInterpolator());

    tickAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

    @Override

    public void onAnimationUpdate(ValueAnimator animation) {

    tickPercent = (float) animation.getAnimatedValue();

    invalidate();

    }

    });

    然后动态绘制的过程,这里又用到了PathMeasure,不太懂得同学可以去搜索了解一下

    canvas.drawArc(rectF, 0, 360, false, solidCirclePaint);

    canvas.drawArc(rectF, 0, 360, false, arcPaint);

    Path path = new Path();

    tickMeasure.getSegment(0, tickPercent * tickMeasure.getLength(), path, true);

    path.rLineTo(0, 0);

    canvas.drawPath(path, arcPaint);

    效果就是这样的了

    5.红叉的绘制

    红叉的绘制就和勾的绘制其实是一样的,这里就不分析了。感兴趣的同学可以去看代码。阿里P6P7【安卓】进阶资料分享+加薪跳槽必备面试题+安卓程序员简历模板​shimo.im

    ▲15G的Android架构进阶、视频资料及安卓程序员简历模板,需要的同学自取;

    大家可以关注专栏,每天都有优质文章分享Android开发架构​zhuanlan.zhihu.com

    展开全文
  • 虚拟机网络IP地址在 /etc/network/interfaces文件中写死了图片3.png (32.17 KB, 下载次数: 0)2020-2-4 19:03 上传3.配置 /etc/resolv.conf 文件如下图片4.png (27.18 KB, 下载次数: 0)2020-2-4 19:...
  • loading下载进度条

    2014-04-07 16:11:30
    Flash制作的Loading下载进度条,包含Fla文件,蓝色的圆圈一直转^-^
  • 超炫下载流程、loading 动效

    千次阅读 2017-08-26 00:01:38
    超炫下载流程、loading 动效;
  • loading下载等待页面flash文件 loading下载等待页面flash文件 loading下载等待页面flash文件
  • loading gif

    千次阅读 2015-12-18 16:23:47
    强烈推荐一个下载loading动图的网站http://preloaders.net/ 可以自己配置参数,生成后直接加载为.gif 可生成透明背景
  • 100多种Loading加载动画,网页制作中用得上哦~
  • ajax方式下载文件附带loading效果 <button type="button" class="btn btn-primary" onclick="doexportexcleAjax()">ajax导出</button> function doexportexcleAjax() { jQuery('#mainList')....
  • 弹窗导出文件,文件类型为三种 !... 需求是在弹窗内显示loading遮罩,并且根据文件下载数目显示进度 正在导出中...(0/2) 正在导出中...(1/2) 正在导出中...(2/2) 导出成功 ...
  • 20个loading动画源文件.AE素材下载 AE、ae源文件、动画源文件
  • 收集的105个网页loading加载gif图标,加载中动画gif。希望对大家有用。
  • boom 光线动态旋转动画,小球左右碰撞,loading音乐旋律动态指示灯,金鱼吐泡泡动画,圆的动画,进度条动画,超级酷炫6种loading加载ppt开场动画源文件下载
  • 一个可以边玩边下载的游戏式Flash Loading动画源文件,在加载的过程中,鼠标可以随意拖动进度条到任意位置,且进度条就像一个档板一样,可以击中下落的小球,小球弹跳到其它地方,你可以像玩游戏一样一边玩一边等待...
  • 这里为大家介绍一个下载loading图标的地址: http://jimpunk.net/Loading/?page_id=9 更有意思的是,国外一个网站已开发出在线制作loading图标,可以生成图片: http://preloaders.net/

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,668
精华内容 1,067
关键字:

下载loading