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

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

2b43406a803bc1a1b8e5ea1899857808.gif

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

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

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

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

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

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仿视频加载旋转小球动画实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值