Material Design Style Widget(二)──MaterialRadioButton(续)

来源:互联网 发布:琉璃神社换的域名2017 编辑:程序博客网 时间:2024/06/06 17:03

前言

最近和同学聊天、看别人的博客,发现自己实现的方式太繁琐了,有很大的优化空间。在这里,利用自定义 Interpolator、属性动画的两个类 ValueAnimator 和 ObjectAnimator对我之前的实现进行优化。

优化

1.利用自定义interpolator,来实现一个Animation 的逆向 Animation。即可以少自定义一个 Animation 类。

    final static class CounterAnticipateInterpolator implements Interpolator{        private float mTension;        CounterAnticipateInterpolator() {            mTension = 2.0f;        }        CounterAnticipateInterpolator(int mTension) {            this.mTension = mTension;        }        @Override        public float getInterpolation(float t) {            return 1 - (t * t * ((mTension + 1) * t - mTension));        }    }

2.当然也可以通过 valueAnimtor 的 addUpdateListener 实现节拍器,不必去自定义 Animation 类。

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);        if (checked){            valueAnimator.setInterpolator(new OvershootInterpolator());        } else {            valueAnimator.setInterpolator(new CounterAnticipateInterpolator());        }        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                update((Float) animation.getAnimatedValue());            }        });        valueAnimator.setDuration(300);        valueAnimator.start();

3.当然我们还可以更进一步,自定义 property,利用 ObjectAnimator,自动的去改变绘制参数,而不必手动的去 update。

    private float interpolatedTime;    public float getInterpolatedTime() {        return interpolatedTime;    }    public void setInterpolatedTime(float interpolatedTime) {        this.interpolatedTime = interpolatedTime;    }    private static final Property<MaterialRadioButton, Float> MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY = new Property<MaterialRadioButton, Float>(Float.class, "MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY") {        @Override        public void set(MaterialRadioButton object, Float value) {            object.setInterpolatedTime(value);        }        @Override        public Float get(MaterialRadioButton object) {            return object.getInterpolatedTime();        }    };        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY, 0 , 1);        if (checked){            objectAnimator.setInterpolator(new OvershootInterpolator());        } else {            objectAnimator.setInterpolator(new CounterAnticipateInterpolator());        }        objectAnimator.setDuration(300);        objectAnimator.start();

源码

1.最终版源码

package com.sinaapp.myron.myronmaterialdesign.widget;import android.animation.ObjectAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Property;import android.view.View;import android.view.animation.Interpolator;import android.view.animation.OvershootInterpolator;public class MaterialRadioButton extends View {    private float cx;    private float cy;    private float outerRingRadius;    private float innerCircleRadiusMax;    private float innerCircleRadius;    private Paint outerBgRingPaint;    private Paint outerFgRingPaint;    private Paint innerCirclePaint;    private int mainColor;    private boolean checked;    private float interpolatedTime;    public float getInterpolatedTime() {        return interpolatedTime;    }    public void setInterpolatedTime(float interpolatedTime) {        this.interpolatedTime = interpolatedTime;    }    private static final Property<MaterialRadioButton, Float> MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY = new Property<MaterialRadioButton, Float>(Float.class, "MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY") {        @Override        public void set(MaterialRadioButton object, Float value) {            object.setInterpolatedTime(value);        }        @Override        public Float get(MaterialRadioButton object) {            return object.getInterpolatedTime();        }    };    public MaterialRadioButton(Context context) {        super(context);    }    public MaterialRadioButton(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MaterialRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        init();    }    private void init() {        int sideLength = Math.min(getWidth(), getHeight());        float halfSideLength = sideLength * 0.5f;        cx = halfSideLength;        cy = halfSideLength;        outerRingRadius = halfSideLength * 0.875f;        float outerRingStrokeWidth = halfSideLength * 0.25f;        innerCircleRadiusMax = halfSideLength * 0.45f;        mainColor = Color.parseColor("#009688");        int outerBgRingColor = Color.parseColor("#616161");        outerBgRingPaint = new Paint();        outerBgRingPaint.setAntiAlias(true);        outerBgRingPaint.setStyle(Paint.Style.STROKE);        outerBgRingPaint.setStrokeWidth(outerRingStrokeWidth);        outerBgRingPaint.setColor(outerBgRingColor);        outerFgRingPaint = new Paint();        outerFgRingPaint.setAntiAlias(true);        outerFgRingPaint.setStyle(Paint.Style.STROKE);        outerFgRingPaint.setStrokeWidth(outerRingStrokeWidth);        outerFgRingPaint.setColor(Color.parseColor("#00ffffff"));        innerCirclePaint = new Paint();        innerCirclePaint.setAntiAlias(true);        innerCirclePaint.setStyle(Paint.Style.FILL);        innerCirclePaint.setColor(Color.parseColor("#00ffffff"));        checked = false;        setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                checked = !checked;                anim();            }        });    }    @Override    protected void onDraw(Canvas canvas) {        calculateDrawParams();        canvas.drawCircle(cx, cy, outerRingRadius, outerBgRingPaint);        canvas.drawCircle(cx, cy, outerRingRadius, outerFgRingPaint);        canvas.drawCircle(cx, cy, innerCircleRadius, innerCirclePaint);    }    private void anim() {        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY, 0, 1);        if (checked) {            objectAnimator.setInterpolator(new OvershootInterpolator());        } else {            objectAnimator.setInterpolator(new CounterAnticipateInterpolator());        }        objectAnimator.setDuration(300);        objectAnimator.start();    }    final static class CounterAnticipateInterpolator implements Interpolator {        private float mTension;        CounterAnticipateInterpolator() {            mTension = 2.0f;        }        CounterAnticipateInterpolator(int mTension) {            this.mTension = mTension;        }        @Override        public float getInterpolation(float t) {            return 1 - (t * t * ((mTension + 1) * t - mTension));        }    }    private void calculateDrawParams() {        //update color of outer foreground ring        int outerFgRingColor = Color.argb(clamp((int) (interpolatedTime * 255), 0, 255), Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));        outerFgRingPaint.setColor(outerFgRingColor);        //update color of inner circle        int innerCircleColor = Color.argb(clamp((int) (interpolatedTime * 255), 0, 255), Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));        innerCirclePaint.setColor(innerCircleColor);        //update radius of inner circle        innerCircleRadius = innerCircleRadiusMax * interpolatedTime;        invalidate();    }    private int clamp(int value, int low, int high) {        return Math.min(Math.max(value, low), high);    }}

2.开发版源码

package com.sinaapp.myron.myronmaterialdesign.widget;import android.animation.Animator;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Property;import android.view.View;import android.view.animation.AlphaAnimation;import android.view.animation.Animation;import android.view.animation.AnticipateInterpolator;import android.view.animation.Interpolator;import android.view.animation.OvershootInterpolator;import android.view.animation.Transformation;public class MaterialRadioButton extends View {    private float cx;    private float cy;    private float outerRingRadius;    private float innerCircleRadiusMax;    private float innerCircleRadius;    private Paint outerBgRingPaint;    private Paint outerFgRingPaint;    private Paint innerCirclePaint;    private int mainColor;    private boolean checked;    private float interpolatedTime;    public float getInterpolatedTime() {        return interpolatedTime;    }    public void setInterpolatedTime(float interpolatedTime) {        this.interpolatedTime = interpolatedTime;    }    private static final Property<MaterialRadioButton, Float> MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY = new Property<MaterialRadioButton, Float>(Float.class, "MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY") {        @Override        public void set(MaterialRadioButton object, Float value) {            object.setInterpolatedTime(value);        }        @Override        public Float get(MaterialRadioButton object) {            return object.getInterpolatedTime();        }    };    public MaterialRadioButton(Context context) {        super(context);    }    public MaterialRadioButton(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MaterialRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        init();    }    private void init() {        int sideLength = Math.min(getWidth(), getHeight());        float halfSideLength = sideLength * 0.5f;        cx = halfSideLength;        cy = halfSideLength;        outerRingRadius = halfSideLength * 0.875f;        float outerRingStrokeWidth = halfSideLength * 0.25f;        innerCircleRadiusMax = halfSideLength * 0.45f;        mainColor = Color.parseColor("#009688");        int outerBgRingColor = Color.parseColor("#616161");        outerBgRingPaint = new Paint();        outerBgRingPaint.setAntiAlias(true);        outerBgRingPaint.setStyle(Paint.Style.STROKE);        outerBgRingPaint.setStrokeWidth(outerRingStrokeWidth);        outerBgRingPaint.setColor(outerBgRingColor);        outerFgRingPaint = new Paint();        outerFgRingPaint.setAntiAlias(true);        outerFgRingPaint.setStyle(Paint.Style.STROKE);        outerFgRingPaint.setStrokeWidth(outerRingStrokeWidth);        outerFgRingPaint.setColor(Color.parseColor("#00ffffff"));        innerCirclePaint = new Paint();        innerCirclePaint.setAntiAlias(true);        innerCirclePaint.setStyle(Paint.Style.FILL);        innerCirclePaint.setColor(Color.parseColor("#00ffffff"));        checked = false;        setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                checked = !checked;                anim();            }        });    }    @Override    protected void onDraw(Canvas canvas) {        calculateDrawParams();        canvas.drawCircle(cx, cy, outerRingRadius, outerBgRingPaint);        canvas.drawCircle(cx, cy, outerRingRadius, outerFgRingPaint);        canvas.drawCircle(cx, cy, innerCircleRadius, innerCirclePaint);    }    private void anim(){        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, MATERIAL_RADIO_BUTTON_PROGRESS_PROPERTY, 0 , 1);        if (checked){            objectAnimator.setInterpolator(new OvershootInterpolator());        } else {            objectAnimator.setInterpolator(new CounterAnticipateInterpolator());        }        objectAnimator.setDuration(300);        objectAnimator.start();        /*        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);        if (checked){            valueAnimator.setInterpolator(new OvershootInterpolator());        } else {            valueAnimator.setInterpolator(new CounterAnticipateInterpolator());        }        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                update((Float) animation.getAnimatedValue());            }        });        valueAnimator.setDuration(300);        valueAnimator.start();        *///        Animation animation = new AlphaAnimation(1, 1);        /*        animation = new CheckAnimation();        if (checked){            animation.setInterpolator(new OvershootInterpolator());        } else {            animation.setInterpolator(new CounterAnticipateInterpolator());        }        */        /*        if (checked){            animation = new CheckAnimation();            animation.setInterpolator(new OvershootInterpolator());        } else {            animation = new UnCheckAnimation();            animation.setInterpolator(new AnticipateInterpolator());        }        *///        animation.setDuration(300);//        animation.setRepeatMode();//        startAnimation(animation);    }/*    class CheckAnimation extends Animation {        @Override        protected void applyTransformation(float interpolatedTime, Transformation t) {            update(interpolatedTime);        }    }  */final static class CounterAnticipateInterpolator implements Interpolator{        private float mTension;        CounterAnticipateInterpolator() {            mTension = 2.0f;        }        CounterAnticipateInterpolator(int mTension) {            this.mTension = mTension;        }        @Override        public float getInterpolation(float t) {            return 1 - (t * t * ((mTension + 1) * t - mTension));        }    }/*    class UnCheckAnimation extends Animation {        @Override        protected void applyTransformation(float interpolatedTime, Transformation t) {            update(1 - interpolatedTime);        }    }*/    private void calculateDrawParams() {        //update color of outer foreground ring        int outerFgRingColor = Color.argb(clamp((int) (interpolatedTime * 255), 0, 255), Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));        outerFgRingPaint.setColor(outerFgRingColor);        //update color of inner circle        int innerCircleColor = Color.argb(clamp((int) (interpolatedTime * 255), 0, 255), Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));        innerCirclePaint.setColor(innerCircleColor);        //update radius of inner circle        innerCircleRadius = innerCircleRadiusMax * interpolatedTime;        invalidate();    }/*    private void update(float interpolatedTime) {        //update color of outer foreground ring        int outerFgRingColor = Color.argb(clamp((int) (interpolatedTime * 255), 0, 255), Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));        outerFgRingPaint.setColor(outerFgRingColor);        //update color of inner circle        int innerCircleColor = Color.argb(clamp((int) (interpolatedTime * 255), 0, 255), Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));        innerCirclePaint.setColor(innerCircleColor);        //update radius of inner circle        innerCircleRadius = innerCircleRadiusMax * interpolatedTime;        invalidate();    }*/    private int clamp(int value, int low, int high) {        return Math.min(Math.max(value, low), high);    }}
0 0
原创粉丝点击