欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

加载动画实现(直线型)

程序员文章站 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

相关标签: 动画 ui 控件