加载动画实现(直线型)
程序员文章站
2022-06-09 20:19:38
...
加载这样的动画常常我们会遇到,但是我们通常就直接去学着第三方库了,但是今天我们要说不,因为我们可以动手去实现一个属于自己的,这感觉可不是只会用*的人能体会的,话不多说,感觉实现一个吧。
下面这个图就是我们UI给的:
下面开始实现它。
就是一个自定义控件,哈哈,又到了上代码时间,走你:
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;
/**
* Created by 23811 on 2017/08/29.
* 整个动画大概样式做出来了,但是会有一点卡顿,我也不知道为啥,知道的同学,望请告知。
*/
public class LoadAnimation extends View {
private Paint paint; //定义直线的颜色和粗度属性
private float width; //控件宽度
private float height; //控件高度
private ValueAnimator animatorin; //一个用来让直线变长的动画
private ValueAnimator animatorout; //一个用来让直线变短的动画
private static float wave = 0; //这个值会取自属性动画,波动为0到半个控件高度
private static int SWITCHANIMATION = 0; //一个标记作用,表示此时执行animatorin动画还是animatorout动画
private Handler handler; //用来实现循环的通讯
private final int IMPLEMENT = 1; //动画准备开始消息通信
// 下面这两个值我们是可以更具需求更改的
private int ANIAMTION_TIME = 500; //每个动画完成时间和延迟时间
private final int COUNT = 10; //我们需要将整个控件展示多少条直线
//这里构造器可有可无,我就留着吧,生怕你们使用的时候出现毛病
public LoadAnimation(Context context) {
super(context);
paint = new Paint();
startAnimation();
}
//这个构造器不可以删除,不信试试
public LoadAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
startAnimation();
}
//测量宽高的方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取控件宽高
width = getMeasuredWidth();
height = getMeasuredHeight();
}
//绘制动画
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.argb(255, 76, 143, 112)); //设置直线颜色,也可以这样设置paint.setColor(Color.RED),但是颜色少
paint.setStrokeWidth(width / COUNT / 2); //设置直线宽度
for (int i = 0; i < COUNT; i++) {
Log.d("widthandheight", "width" + width + "height" + height);
// 这里的绘制过程大家可能看不懂,不要紧,下面的一波注释会解释的
float postionX = width / (COUNT * 2) * (COUNT * 2 - i * 2 - 1);
float postionY = (wave - (height - (height / COUNT) * (i + 1)) / 2);
/** 为什么下面会绘制两个直线呢?我们注意观看动画就知道,动画的直线是从中间往上下扩展或收缩的,
* 所以要将看起来的一根直线,分两个直线绘制出来,一个往上绘制,一个往下绘制,懂不。
**/
canvas.drawLine(postionX, height / 2, postionX, height / 2 - postionY, paint);
canvas.drawLine(postionX, height / 2, postionX, height / 2 + postionY, paint);
}
//绘制十根直线,这里我注释掉了为什么还留着呢,因为上面的两个绘制就是从下面这个总结来的,这里不删,也是方便你们看看上面的两个式子怎么来的
// canvas.drawLine(width / 20 * 19, height / 2, width / 20 * 19, height / 2 - (wave - 360), paint);
// canvas.drawLine(width / 20 * 19, height / 2, width / 20 * 19, height / 2 + (wave - 360), paint);
// canvas.drawLine(width / 20 * 17, height / 2, width / 20 * 17, height / 2 - (wave - 320), paint);
// canvas.drawLine(width / 20 * 17, height / 2, width / 20 * 17, height / 2 + (wave - 320), paint);
// canvas.drawLine(width / 20 * 15, height / 2, width / 20 * 15, height / 2 - (wave - 280), paint);
// canvas.drawLine(width / 20 * 15, height / 2, width / 20 * 15, height / 2 + (wave - 280), paint);
// canvas.drawLine(width / 20 * 13, height / 2, width / 20 * 13, height / 2 - (wave - 240), paint);
// canvas.drawLine(width / 20 * 13, height / 2, width / 20 * 13, height / 2 + (wave - 240), paint);
// canvas.drawLine(width / 20 * 11, height / 2, width / 20 * 11, height / 2 - (wave - 200), paint);
// canvas.drawLine(width / 20 * 11, height / 2, width / 20 * 11, height / 2 + (wave - 200), paint);
// canvas.drawLine(width / 20 * 9, height / 2, width / 20 * 9, height / 2 - (wave - 160), paint);
// canvas.drawLine(width / 20 * 9, height / 2, width / 20 * 9, height / 2 + (wave - 160), paint);
// canvas.drawLine(width / 20 * 7, height / 2, width / 20 * 7, height / 2 - (wave - 120), paint);
// canvas.drawLine(width / 20 * 7, height / 2, width / 20 * 7, height / 2 + (wave - 120), paint);
// canvas.drawLine(width / 20 * 5, height / 2, width / 20 * 5, height / 2 - (wave - 80), paint);
// canvas.drawLine(width / 20 * 5, height / 2, width / 20 * 5, height / 2 + (wave - 80), paint);
// canvas.drawLine(width / 20 * 3, height / 2, width / 20 * 3, height / 2 - (wave - 40), paint);
// canvas.drawLine(width / 20 * 3, height / 2, width / 20 * 3, height / 2 + (wave - 40), paint);
// canvas.drawLine(width / 20, height / 2, width / 20, height / 2 - wave, paint);
// canvas.drawLine(width / 20, height / 2, width / 20, height / 2 + wave, paint);
}
//实现动画的方法,这里就给wave赋了值,从而出现动画效果,但是循环的实现在startAnimation方法里面
// 动画我们使用的是属性动画,不懂的同学可参考:http://blog.csdn.net/harvic880925/article/details/50525521
private void initAnimator(long duration) {
TimeInterpolator timeInterpolator = new LinearInterpolator(); //匀速插值器
//让直线变长的动画
if (SWITCHANIMATION == 0) {
if (animatorout != null && animatorout.isRunning()) {
animatorout.cancel();
} else {
animatorin = ValueAnimator.ofFloat(0, height / 2).setDuration(duration);
animatorin.setInterpolator(timeInterpolator);
animatorin.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
wave = (float) animation.getAnimatedValue();
Log.d("getAnimatedValue", wave + "");
invalidate(); //刷新页面
}
});
animatorin.start();
}
SWITCHANIMATION = 1;
} else {
//让直线变短的动画
if (animatorin != null && animatorin.isRunning()) {
animatorin.cancel();
} else {
animatorout = ValueAnimator.ofFloat(height / 2, 0).setDuration(duration);
animatorout.setInterpolator(timeInterpolator);
animatorout.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
wave = (float) animation.getAnimatedValue();
invalidate(); //刷新页面
}
});
animatorout.start();
}
SWITCHANIMATION = 0;
}
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
initAnimator(ANIAMTION_TIME); //初始化动画
}
//开始动画,这里面实现了循环,这就保证了动画在一直进行着
public void startAnimation() {
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case IMPLEMENT:
initAnimator(ANIAMTION_TIME);
startAnimation();
break;
}
}
};
new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(ANIAMTION_TIME); //延迟1秒后进行下一个动画,保证下一个动画不会影响到上一个动画,因为执行一个动画需要1秒
Message message = new Message();
message.what = IMPLEMENT;
handler.sendMessage(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
哈哈,贯彻我一贯的风格,注释全在代码里,可能有的额同学觉得代码比较长,那么我防止你们毫无头绪的看,我给个顺序吧.
1:构造器,
2:onMeasure方法
3:onWindowFocusChanged方法
4:initAnimator方法
5:startAnimation方法
好了,就说到这,下面给出大家可能想要的DEMO:
http://download.csdn.net/download/wanxuedong/9956985