首页 > 系统 > Android > 正文

Android仿视频加载旋转小球动画效果的实例代码

2019-10-21 21:39:17
字体:
来源:转载
供稿:网友

先上个效果图,以免大家跑错地了。    

Android,视频加载,旋转,动画,代码

嗯,除了只能录三秒,其他没啥问题。   

下面分析一下怎么实现上面这个效果。    

理性分析后我们可以看到是几个小球绕着一个圆进行运动,那这里面的重点我们看看什么。    

绘制五个球,没什么难度,让球绕圆进行运动,这个好像我们没有见到是怎么去实现了,那下就说这个。    

从本质上看,球绕圆运动,其实我们可以看作是一个物体绕指定的路劲运动,那我们就有下面几个东西需要说一下:

1:Path
2:ValueAnimator
3:PathMeasure  

前两个大家应该都见过,一个是路径,就是可以自己绘制路线的一个工具,一个是动画,用来指定物体运动的工具,那第三个是一个关于测量路径的类。    

下面说说PathMeasure的用法。    

首先是初始化:

pathMeasure = new PathMeasure(path, false);  

两个参数第一个,第一个就是我们需要用到的路径,第二个参数意思就是这个以路径头尾是否相连来计算结果,通常我们就写false就行,不会有问题。    

然后是用法:

private float[] mCurrentPositionOne = new float[2];float value = (Float) animation.getAnimatedValue();pathMeasure.getPosTan(value, mCurrentPositionOne, null);  我们可以看见把一个二维数组放到了getPosTan这个方法里面,然后还有一个animation,这里的animation来自哪里呢?来自这里:valueAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  @Override  public void onAnimationUpdate(ValueAnimator animation) {    // 获取当前点坐标封装到mCurrentPosition    float value = (Float) animation.getAnimatedValue();    pathMeasure.getPosTan(value, mCurrentPositionOne, null);    postInvalidate();  }});

看见没,是动画的监听里面来的,getPosTan的最后一个参数通常也就写null就行了,那么这整个一行的代码意思就是当动画发生了变化,就执行这行代码,然后这行代码会把这个时间点的路径上的坐标赋值给mCurrentPositionOne。   

那我们获取到看这个路径上的坐标点怎么办呢?   

立马用来ondraw里面啊,我的小球此时就可以根据这个坐标点去绘制自己的位置,这个的话,当动画开始时,小球就会不断接受新的坐标,然后不断重绘,最终产生旋转小球的效果。     

我先把属性动画的代码贴出来:

if (valueAnimatorOne == null) {   valueAnimatorOne = ValueAnimator.ofFloat(0, pathMeasure.getLength());  valueAnimatorOne.setDuration(800);  // 减速插值器  valueAnimatorOne.setInterpolator(new DecelerateInterpolator());  valueAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator animation) {      // 获取当前点坐标封装到mCurrentPosition      float value = (Float) animation.getAnimatedValue();      pathMeasure.getPosTan(value, mCurrentPositionOne, null);      postInvalidate();    }  });  valueAnimatorOne.addListener(new Animator.AnimatorListener() {    @Override    public void onAnimationStart(Animator animator) {      finishAnimateOne = 1;    }    @Override    public void onAnimationEnd(Animator animator) {      finishAnimateOne = 0;    }    @Override    public void onAnimationCancel(Animator animator) {    }    @Override    public void onAnimationRepeat(Animator animator) {    }  });}valueAnimatorOne.start();

  我写了个800,也就是动画的维持时间,但是我们发现有啊后几个小球,所以我们需要绘制好几个小球,然后给他们不同的动画,为什么呢?因为动画都一样,小球就叠加在一起了,我们就只能看见一个球了。   

说到这里的话,我们的目标算时完成了,具体的操作,大家参考以下代码,或者去:android自定义View索引     

里面动画的demo进行下载,大家随意,下面给出代码:

/** * 仿视频加载动画,旋转的蓝色小球 */public class RotaryBall extends View {  private Path rotationPath;  private float radius;  private Paint circlePaintOne;  private PathMeasure pathMeasure;  private int finishAnimateOne = 0;  // 用来判断当前动画有没有开始  private int finishAnimateTwo = 0;  // 用来判断当前动画有没有开始  private int finishAnimateThree = 0;  // 用来判断当前动画有没有开始  private int finishAnimateFour = 0;  // 用来判断当前动画有没有开始  private int finishAnimateFive = 0;  // 用来判断当前动画有没有开始  private Handler handler;  private float[] mCurrentPositionOne = new float[2];  private float[] mCurrentPositionTwo = new float[2];  private float[] mCurrentPositionThree = new float[2];  private float[] mCurrentPositionFour = new float[2];  private float[] mCurrentPositionFive = new float[2];  private ValueAnimator valueAnimatorOne = null;  private ValueAnimator valueAnimatorTwo = null;  private ValueAnimator valueAnimatorThree = null;  private ValueAnimator valueAnimatorFour = null;  private ValueAnimator valueAnimatorFive = null;  private int currentStatus = -1;  //-1表示第一次运行,0表示动画结束或者没开始,1表示正在运动中  private boolean animateOrNot = true;  //用来决定是否开启动画  public RotaryBall(Context context) {    super(context);    initData();  }  public RotaryBall(Context context, AttributeSet attrs) {    super(context, attrs);    initData();  }  private void initData() {    rotationPath = new Path();    circlePaintOne = new Paint();    circlePaintOne.setColor(Color.BLUE);    circlePaintOne.setAntiAlias(true);    handler = new Handler() {      @Override      public void handleMessage(Message msg) {        super.handleMessage(msg);        switch (msg.what) {          case 4:            if (finishAnimateOne == 0) {              startAnimatorOne();            }            if (finishAnimateTwo == 0) {              startAnimatorTwo();            }            if (finishAnimateThree == 0) {              startAnimatorThree();            }            if (finishAnimateFour == 0) {              startAnimatorFour();            }            if (finishAnimateFive == 0) {              startAnimatorFive();            }            currentStatus = 0;        }      }    };  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    radius = getMeasuredWidth() / 2;  }  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);//    rotationPath.addCircle(radius, radius, radius - 10, CW);    rotationPath.moveTo(radius, 0 + 10);    rotationPath.cubicTo(radius, 0 + 10, radius * 2 - 10, 0 + 10, radius * 2 - 10, radius);    rotationPath.cubicTo(radius * 2 - 10, radius, radius * 2 - 10, radius * 2 - 10, radius, radius * 2 - 10);    rotationPath.cubicTo(radius, radius * 2 - 10, 0 + 10, radius * 2 - 10, 0 + 10, radius);    rotationPath.cubicTo(0 + 10, radius, 0 + 10, 0 + 10, radius, 0 + 10);    rotationPath.close();    pathMeasure = new PathMeasure(rotationPath, false);    //下面绘制不同半径的小圆    canvas.drawCircle(mCurrentPositionOne[0], mCurrentPositionOne[1], 10, circlePaintOne);    canvas.drawCircle(mCurrentPositionTwo[0], mCurrentPositionTwo[1], 9, circlePaintOne);    canvas.drawCircle(mCurrentPositionThree[0], mCurrentPositionThree[1], 7, circlePaintOne);    canvas.drawCircle(mCurrentPositionFour[0], mCurrentPositionFour[1], 5, circlePaintOne);    canvas.drawCircle(mCurrentPositionFive[0], mCurrentPositionFive[1], 3, circlePaintOne);    if (currentStatus == -1) {      Message message = new Message();      message.what = 4;      handler.sendMessage(message);    }    if (animateOrNot) {      if (currentStatus == 0) {        currentStatus = 1;        new Thread() {      //用线程来统一五个圆的周期          @Override          public void run() {            super.run();            try {              Log.d("thread", "thread");              Thread.sleep(1600);              Message message = new Message();              message.what = 4;              handler.sendMessage(message);            } catch (InterruptedException e) {              e.printStackTrace();            }          }        }.start();      }    }  }  //供外部调用,开始动画  public void startAnimate() {    if (!animateOrNot) {      animateOrNot = true;      currentStatus = -1;      invalidate();    }  }  //供外部调用,停止动画  public void stopAnimate() {    if (animateOrNot) {      animateOrNot = false;    }  }  //界面被销毁  @Override  protected void onDetachedFromWindow() {    super.onDetachedFromWindow();    stopAnimate();    clearAllAnimation();  }  //清除所有动画效果  private void clearAllAnimation() {    if (valueAnimatorOne != null){      if (valueAnimatorOne.isRunning()){        valueAnimatorOne.cancel();      }      valueAnimatorOne.removeAllUpdateListeners();      valueAnimatorOne = null;    }    if (valueAnimatorTwo != null){      if (valueAnimatorTwo.isRunning()){        valueAnimatorTwo.cancel();      }      valueAnimatorTwo.removeAllUpdateListeners();      valueAnimatorTwo = null;    }    if (valueAnimatorThree != null){      if (valueAnimatorThree.isRunning()){        valueAnimatorThree.cancel();      }      valueAnimatorThree.removeAllUpdateListeners();      valueAnimatorThree = null;    }    if (valueAnimatorFour != null){      if (valueAnimatorFour.isRunning()){        valueAnimatorFour.cancel();      }      valueAnimatorFour.removeAllUpdateListeners();      valueAnimatorFour = null;    }    if (valueAnimatorFive != null){      if (valueAnimatorFive.isRunning()){        valueAnimatorFive.cancel();      }      valueAnimatorFive.removeAllUpdateListeners();      valueAnimatorFive = null;    }  }  //开始第一个小球的动画  private void startAnimatorOne() {    if (valueAnimatorOne == null) {      Log.d("valueAnimatorOne", "valueAnimatorOne");      valueAnimatorOne = ValueAnimator.ofFloat(0, pathMeasure.getLength());      valueAnimatorOne.setDuration(800);      // 减速插值器      valueAnimatorOne.setInterpolator(new DecelerateInterpolator());      valueAnimatorOne.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {          // 获取当前点坐标封装到mCurrentPosition          float value = (Float) animation.getAnimatedValue();          pathMeasure.getPosTan(value, mCurrentPositionOne, null);          postInvalidate();        }      });      valueAnimatorOne.addListener(new Animator.AnimatorListener() {        @Override        public void onAnimationStart(Animator animator) {          finishAnimateOne = 1;        }        @Override        public void onAnimationEnd(Animator animator) {          finishAnimateOne = 0;        }        @Override        public void onAnimationCancel(Animator animator) {        }        @Override        public void onAnimationRepeat(Animator animator) {        }      });    }    valueAnimatorOne.start();  }  //开始第二个小球的动画  private void startAnimatorTwo() {    if (valueAnimatorTwo == null) {      valueAnimatorTwo = ValueAnimator.ofFloat(0, pathMeasure.getLength());      valueAnimatorTwo.setDuration(1000);      // 减速插值器      valueAnimatorTwo.setInterpolator(new DecelerateInterpolator());      valueAnimatorTwo.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {          float value = (Float) animation.getAnimatedValue();          // 获取当前点坐标封装到mCurrentPosition          pathMeasure.getPosTan(value, mCurrentPositionTwo, null);          postInvalidate();        }      });      valueAnimatorTwo.addListener(new Animator.AnimatorListener() {        @Override        public void onAnimationStart(Animator animator) {          finishAnimateTwo = 1;        }        @Override        public void onAnimationEnd(Animator animator) {          finishAnimateTwo = 0;        }        @Override        public void onAnimationCancel(Animator animator) {        }        @Override        public void onAnimationRepeat(Animator animator) {        }      });    }    valueAnimatorTwo.start();  }  //开始第三个小球的动画  private void startAnimatorThree() {    if (valueAnimatorThree == null) {      valueAnimatorThree = ValueAnimator.ofFloat(0, pathMeasure.getLength());      valueAnimatorThree.setDuration(1200);      // 减速插值器      valueAnimatorThree.setInterpolator(new DecelerateInterpolator());      valueAnimatorThree.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {          float value = (Float) animation.getAnimatedValue();          // 获取当前点坐标封装到mCurrentPosition          pathMeasure.getPosTan(value, mCurrentPositionThree, null);          postInvalidate();        }      });      valueAnimatorThree.addListener(new Animator.AnimatorListener() {        @Override        public void onAnimationStart(Animator animator) {          finishAnimateThree = 1;        }        @Override        public void onAnimationEnd(Animator animator) {          finishAnimateThree = 0;        }        @Override        public void onAnimationCancel(Animator animator) {        }        @Override        public void onAnimationRepeat(Animator animator) {        }      });    }    valueAnimatorThree.start();  }  //开始第四个小球的动画  private void startAnimatorFour() {    if (valueAnimatorFour == null) {      valueAnimatorFour = ValueAnimator.ofFloat(0, pathMeasure.getLength());      valueAnimatorFour.setDuration(1400);      // 减速插值器      valueAnimatorFour.setInterpolator(new DecelerateInterpolator());      valueAnimatorFour.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {          float value = (Float) animation.getAnimatedValue();          // 获取当前点坐标封装到mCurrentPosition          pathMeasure.getPosTan(value, mCurrentPositionFour, null);          postInvalidate();        }      });      valueAnimatorFour.addListener(new Animator.AnimatorListener() {        @Override        public void onAnimationStart(Animator animator) {          finishAnimateFour = 1;        }        @Override        public void onAnimationEnd(Animator animator) {          finishAnimateFour = 0;        }        @Override        public void onAnimationCancel(Animator animator) {        }        @Override        public void onAnimationRepeat(Animator animator) {        }      });    }    valueAnimatorFour.start();  }  //开始第五个小球的动画  private void startAnimatorFive() {    if (valueAnimatorFive == null) {      valueAnimatorFive = ValueAnimator.ofFloat(0, pathMeasure.getLength());      valueAnimatorFive.setDuration(1600);      // 减速插值器      valueAnimatorFive.setInterpolator(new DecelerateInterpolator());      valueAnimatorFive.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {          float value = (Float) animation.getAnimatedValue();          // 获取当前点坐标封装到mCurrentPosition          pathMeasure.getPosTan(value, mCurrentPositionFive, null);          postInvalidate();        }      });      valueAnimatorFive.addListener(new Animator.AnimatorListener() {        @Override        public void onAnimationStart(Animator animator) {          finishAnimateFive = 1;        }        @Override        public void onAnimationEnd(Animator animator) {          finishAnimateFive = 0;        }        @Override        public void onAnimationCancel(Animator animator) {        }        @Override        public void onAnimationRepeat(Animator animator) {        }      });    }    valueAnimatorFive.start();  }}

总结

以上所述是小编给大家介绍的Android仿视频加载旋转小球动画实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对VEVB武林网网站的支持!


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表