Android 自定义View 实现loading动画

自定义View的步骤:


1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure (有时非必须)

4、重写onDraw 


找到res/values/attrs.xml(没有则需创建)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--自定义属性集-->
    <declare-styleable name="LoadCircleView">
        <!--圆的半径-->
        <attr name="circle_radius" format="float" />
        <!--持续时间-->
        <attr name="duration" format="integer" />
    </declare-styleable>
</resources>
编写我们的View

public class LoadCircleView extends View {

    /**
     * 第一个动画的索引
     */
    private int changeIndex = 0;

    /**
     * 圆的颜色值
     */
    private int[] colors = new int[]{
            getResources().getColor(R.color.color_red),
            getResources().getColor(R.color.color_blue),
            getResources().getColor(R.color.color_black)};

    /**
     * 偏移量
     */
    private Float maxWidth = 50f;

    /**
     * 圆的半径 默认10f
     */
    private Float circleRadius = 10f;

    /**
     * 当前偏移的X坐标
     */
    private Float currentX = 0f;

    /**
     * 画笔
     */
    private Paint paint;

    /**
     * 属性动画
     */
    private ValueAnimator valueAnimator;
    /**
     * 持续时间
     */
    private int duration = 800;


    /**
     * 默认的布局文件调用的是两个参数的构造方法
     * 让所有的构造调用我们的三个参数的构造
     * 在三个参数的构造中获得自定义属性
     */
    public LoadCircleView(Context context) {
        this(context,null);
    }

    public LoadCircleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LoadCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        if (null != attrs) {
            //获得对控件自定义属性集的引用
            TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.LoadCircleView);
            circleRadius = typedArray.getFloat(R.styleable.LoadCircleView_circle_radius,circleRadius);
            duration = typedArray.getInt(R.styleable.LoadCircleView_duration,duration);
            typedArray.recycle();//记得回收
        }
        startAnimator();
    }

    /**
     * 位移动画
     */
    private void startAnimator(){
        valueAnimator = ValueAnimator.ofFloat(0f,maxWidth,0);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentX = (Float)animation.getAnimatedValue();
                invalidate();
            }
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                changePoint(changeIndex);
            }
        });
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setRepeatCount(-1);
        valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
        valueAnimator.setDuration(duration);
        valueAnimator.start();
    }

    /**
     * 先执行动画的目标和中间停止的动画目标交换
     *
     * @param index 最先执行的动画的索引
     */
    private void changePoint(int index) {
        int temp = colors[2];
        colors[2] = colors[index];
        colors[index] = temp;
        changeIndex = (index == 0) ? 1 : 0;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        /**左边圆**/
        paint.setColor(colors[0]);
        canvas.drawCircle(centerX - currentX, centerY, circleRadius, paint);
        /**右边圆**/
        paint.setColor(colors[1]);
        canvas.drawCircle(centerX + currentX, centerY, circleRadius, paint);
        /**中间圆**/
        paint.setColor(colors[2]);
        canvas.drawCircle(centerX, centerY, circleRadius, paint);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        valueAnimator.cancel();
    }
}

View的构造方法中,获取我们的属性,并开始动画

使用ValueAnimator实现动画的步骤:

1. 调用ValueAnimation类中的ofInt(int...values)、ofFloat(String propertyName,float...values)等静态方法实例化ValueAnimator对象,并设置目标属性的属性名、初始值或结束值等值;
2.调用addUpdateListener(AnimatorUpdateListener mListener)方法为ValueAnimator对象设置属性变化的监听器;

3.创建自定义的Interpolator,调用setInterpolator(TimeInterpolator value)为ValueAniamtor设置自定义的Interpolator;(可选,不设置默认为缺省值)
4.创建自定义的TypeEvaluator,调用setEvaluator(TypeEvaluator value)为ValueAnimator设置自定义的TypeEvaluator;(可选,不设置默认为缺省值)
5.在AnimatorUpdateListener 中的实现方法为目标对象的属性设置计算好的属性值。
6.设置动画的持续时间、是否重复及重复次数等属性;
7.为ValueAnimator设置目标对象并开始执行动画。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值