Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

加载动画实现(直线型)

$
0
0

      加载这样的动画常常我们会遇到,但是我们通常就直接去学着第三方库了,但是今天我们要说不,因为我们可以动手去实现一个属于自己的,这感觉可不是只会用轮子的人能体会的,话不多说,感觉实现一个吧。
      下面这个图就是我们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

作者:wanxuedong 发表于2017/8/30 12:18:20 原文链接
阅读:41 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>