今天无意间看到雅虎视频里面的加载动画挺有趣的。效果如下:
就尝试自己用自定义view简单的实现一下,效果图如下:
其实主要就是两个圆弧的变化加上一个旋转动画。
首先定义一个自定义view类 YahooloadingView。定义出需要使用到的参数:
private Paint paint;
private RectF rectF;
private int width = 360;
private int progress = 0;
private int status = 1;
private int startOne = 0;
private int startTwo = 180;
private int endOne = progress;
private int endTwo = progress;
这里为了方便,我们将view的直径写死为固定360,定义出两段圆弧的初始位置和弧度。
然后进行测量:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(width, width);
}
最后进行绘制:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paintLoadview(canvas);
}
private void paintLoadview(Canvas canvas) {
canvas.drawArc(rectF, startOne, endOne, false, paint);
canvas.drawArc(rectF, startTwo, endTwo, false, paint);
}
简单的几行代码后,我们得到了两段圆弧。那么怎样让它动起来呢?
核心逻辑:
第一,使用handler来更改数据达到更新ui的目的。
第二,观察原动画的圆弧变化规律,发现圆弧有两个阶段,一阶段为正常伸长,另一阶段为反向缩短。因此我们使用status来区分与圆弧的两个阶段。正常伸长时,初始位置不变,弧度变长;反向缩短时,弧度变短,圆弧末端不变,初始位置随弧度变化。
第三,创建旋转动画 rotateAnimation,让view旋转起来。
第一二步:
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (progress >= 180) {
status = -1;
}
if (progress <= 0) {
status = 3;
}
progress += status;
endOne = progress;
endTwo = progress;
if (status == -1) {
startOne = 180 - progress;
}
if (startOne >= 180) {
startOne = 0;
}
if (status == -1) {
startTwo = 360 - progress;
}
if (startTwo >= 360) {
startTwo = 180;
}
invalidate();
return true;
}
});
第三步:
private void initAnimation() {
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(12000); //设置动画播放时长
rotateAnimation.setRepeatCount(Animation.INFINITE); //设置动画循环播放
rotateAnimation.setInterpolator(new LinearInterpolator()); //设置动画以均匀的速率在改变
this.startAnimation(rotateAnimation);
}
这样就实现了循环更新ui的功能了,整个view的代码就差不多了,因为代码不是很多,就把源码全部贴出来吧。
package com.benhuan.myyahooloadingviewdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.CycleInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
/**
* Created by xieminfeng on 2016/11/9.
*/
public class Yahooloadingview extends View {
private Paint paint;
private RectF rectF;
private int width = 360;
private int progress = 0;
private int status = 1;
private int startOne = 0;
private int startTwo = 180;
private int endOne = progress;
private int endTwo = progress;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (progress >= 180) {
status = -1;
}
if (progress <= 0) {
status = 3;
}
progress += status;
endOne = progress;
endTwo = progress;
if (status == -1) {
startOne = 180 - progress;
}
if (startOne >= 180) {
startOne = 0;
}
if (status == -1) {
startTwo = 360 - progress;
}
if (startTwo >= 360) {
startTwo = 180;
}
invalidate();
return true;
}
});
public Yahooloadingview(Context context) {
this(context, null);
}
public Yahooloadingview(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Yahooloadingview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
initRectF();
initThread();
initAnimation();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(width, width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paintLoadview(canvas);
}
private void paintLoadview(Canvas canvas) {
canvas.drawArc(rectF, startOne, endOne, false, paint);
canvas.drawArc(rectF, startTwo, endTwo, false, paint);
}
private void initPaint() {
paint = new Paint();
paint.setColor(Color.RED);
paint.setAntiAlias(true);
paint.setStrokeWidth(30);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
}
private void initRectF() {
rectF = new RectF(30, 30, width - 30, width - 30);
}
private void initThread() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
handler.sendEmptyMessageDelayed(0, 1000);
SystemClock.sleep(8);
}
}
}).start();
}
private void initAnimation() {
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(12000); //设置动画播放时长
rotateAnimation.setRepeatCount(Animation.INFINITE); //设置动画循环播放
rotateAnimation.setInterpolator(new LinearInterpolator()); //设置动画以均匀的速率在改变
this.startAnimation(rotateAnimation);
}
}