自定义SwitchButton切换样式,一行代码搞定(转)

使用步骤:

1,把自定义SwitchButton放进去

import android.animation.Animator;

import android.animation.ValueAnimator;

import android.annotation.TargetApi;

import android.content.Context;

import android.content.res.Resources;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.RectF;

import android.os.Build;

import android.util.AttributeSet;

import android.util.TypedValue;

import android.view.MotionEvent;

import android.view.View;

import android.widget.Checkable;

public class SwitchButtonextends Viewimplements Checkable {

private static final int DEFAULT_WIDTH =dp2pxInt(58);

    private static final int DEFAULT_HEIGHT =dp2pxInt(36);

    /**

* 动画状态:

* 1.静止

* 2.进入拖动

* 3.处于拖动

* 4.拖动-复位

* 5.拖动-切换

* 6.点击切换

* **/

    private final int ANIMATE_STATE_NONE =0;

    private final int ANIMATE_STATE_PENDING_DRAG =1;

    private final int ANIMATE_STATE_DRAGING =2;

    private final int ANIMATE_STATE_PENDING_RESET =3;

    private final int ANIMATE_STATE_PENDING_SETTLE =4;

    private final int ANIMATE_STATE_SWITCH =5;

    public SwitchButton(Context context) {

super(context);

        init(context, null);

    }

public SwitchButton(Context context, AttributeSet attrs) {

super(context, attrs);

        init(context, attrs);

    }

public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

        init(context, attrs);

    }

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

        init(context, attrs);

    }

@Override

    public final void setPadding(int left, int top, int right, int bottom) {

super.setPadding(0, 0, 0, 0);

    }

/**

* 初始化参数

*/

    private void init(Context context, AttributeSet attrs) {

TypedArray typedArray =null;

        if(attrs !=null){

typedArray = context.obtainStyledAttributes(attrs, R.styleable.SwitchButton);

        }

shadowEffect =optBoolean(typedArray,

                R.styleable.SwitchButton_sb_shadow_effect,

                true);

        uncheckCircleColor =optColor(typedArray,

                R.styleable.SwitchButton_sb_uncheckcircle_color,

                0XffAAAAAA);//0XffAAAAAA;

        uncheckCircleWidth =optPixelSize(typedArray,

                R.styleable.SwitchButton_sb_uncheckcircle_width,

                dp2pxInt(1.5f));//dp2pxInt(1.5f);

        uncheckCircleOffsetX =dp2px(10);

        uncheckCircleRadius =optPixelSize(typedArray,

                R.styleable.SwitchButton_sb_uncheckcircle_radius,

                dp2px(4));//dp2px(4);

        checkedLineOffsetX =dp2px(4);

        checkedLineOffsetY =dp2px(4);

        shadowRadius =optPixelSize(typedArray,

                R.styleable.SwitchButton_sb_shadow_radius,

                dp2pxInt(2.5f));//dp2pxInt(2.5f);

        shadowOffset =optPixelSize(typedArray,

                R.styleable.SwitchButton_sb_shadow_offset,

                dp2pxInt(1.5f));//dp2pxInt(1.5f);

        shadowColor =optColor(typedArray,

                R.styleable.SwitchButton_sb_shadow_color,

                0X33000000);//0X33000000;

        uncheckColor =optColor(typedArray,

                R.styleable.SwitchButton_sb_uncheck_color,

                0XffDDDDDD);//0XffDDDDDD;

        checkedColor =optColor(typedArray,

                R.styleable.SwitchButton_sb_checked_color,

                0Xff51d367);//0Xff51d367;

        borderWidth =optPixelSize(typedArray,

                R.styleable.SwitchButton_sb_border_width,

                dp2pxInt(1));//dp2pxInt(1);

        checkLineColor =optColor(typedArray,

                R.styleable.SwitchButton_sb_checkline_color,

                Color.WHITE);//Color.WHITE;

        checkLineWidth =optPixelSize(typedArray,

                R.styleable.SwitchButton_sb_checkline_width,

                dp2pxInt(1f));//dp2pxInt(1.0f);

        checkLineLength =dp2px(6);

        int buttonColor =optColor(typedArray,

                R.styleable.SwitchButton_sb_button_color,

                Color.WHITE);//Color.WHITE;

        int effectDuration =optInt(typedArray,

                R.styleable.SwitchButton_sb_effect_duration,

                300);//300;

        isChecked =optBoolean(typedArray,

                R.styleable.SwitchButton_sb_checked,

                false);

        showIndicator =optBoolean(typedArray,

                R.styleable.SwitchButton_sb_show_indicator,

                true);

        background =optColor(typedArray,

                R.styleable.SwitchButton_sb_background,

                Color.WHITE);//Color.WHITE;

        enableEffect =optBoolean(typedArray,

                R.styleable.SwitchButton_sb_enable_effect,

                true);

        if(typedArray !=null){

typedArray.recycle();

        }

paint =new Paint(Paint.ANTI_ALIAS_FLAG);

        buttonPaint =new Paint(Paint.ANTI_ALIAS_FLAG);

        buttonPaint.setColor(buttonColor);

        if(shadowEffect){

buttonPaint.setShadowLayer(

shadowRadius,

                    0, shadowOffset,

                    shadowColor);

        }

viewState =new ViewState();

        beforeState =new ViewState();

        afterState =new ViewState();

        valueAnimator = ValueAnimator.ofFloat(0f, 1f);

        valueAnimator.setDuration(effectDuration);

        valueAnimator.setRepeatCount(0);

        valueAnimator.addUpdateListener(animatorUpdateListener);

        valueAnimator.addListener(animatorListener);

        super.setClickable(true);

        this.setPadding(0, 0, 0, 0);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

setLayerType(LAYER_TYPE_SOFTWARE, null);

        }

}

@Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

final int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if(widthMode == MeasureSpec.UNSPECIFIED

                || widthMode == MeasureSpec.AT_MOST){

widthMeasureSpec = MeasureSpec.makeMeasureSpec(DEFAULT_WIDTH, MeasureSpec.EXACTLY);

        }

if(heightMode == MeasureSpec.UNSPECIFIED

                || heightMode == MeasureSpec.AT_MOST){

heightMeasureSpec = MeasureSpec.makeMeasureSpec(DEFAULT_HEIGHT, MeasureSpec.EXACTLY);

        }

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

@Override

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

        float viewPadding = Math.max(shadowRadius +shadowOffset, borderWidth);

        height = h - viewPadding - viewPadding;

        width = w - viewPadding - viewPadding;

        viewRadius =height *.5f;

        buttonRadius =viewRadius -borderWidth;

        left = viewPadding;

        top = viewPadding;

        right = w - viewPadding;

        bottom = h - viewPadding;

        centerX = (left +right) *.5f;

        centerY = (top +bottom) *.5f;

        buttonMinX =left +viewRadius;

        buttonMaxX =right -viewRadius;

        if(isChecked()){

setCheckedViewState(viewState);

        }else{

setUncheckViewState(viewState);

        }

isUiInited =true;

        postInvalidate();

    }

/**

    * @param viewState

    */

    private void setUncheckViewState(ViewState viewState){

viewState.radius =0;

        viewState.checkStateColor =uncheckColor;

        viewState.checkedLineColor = Color.TRANSPARENT;

        viewState.buttonX =buttonMinX;

    }

/**

    * @param viewState

    */

    private void setCheckedViewState(ViewState viewState){

viewState.radius =viewRadius;

        viewState.checkStateColor =checkedColor;

        viewState.checkedLineColor =checkLineColor;

        viewState.buttonX =buttonMaxX;

    }

@Override

    protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

        paint.setStrokeWidth(borderWidth);

        paint.setStyle(Paint.Style.FILL);

        //绘制白色背景

        paint.setColor(background);

        drawRoundRect(canvas,

                left, top, right, bottom,

                viewRadius, paint);

        //绘制关闭状态的边框

        paint.setStyle(Paint.Style.STROKE);

        paint.setColor(uncheckColor);

        drawRoundRect(canvas,

                left, top, right, bottom,

                viewRadius, paint);

        //绘制小圆圈

        if(showIndicator){

drawUncheckIndicator(canvas);

        }

//绘制开启背景色

        float des =viewState.radius *.5f;//[0-backgroundRadius*0.5f]

        paint.setStyle(Paint.Style.STROKE);

        paint.setColor(viewState.checkStateColor);

        paint.setStrokeWidth(borderWidth + des *2f);

        drawRoundRect(canvas,

                left + des, top + des, right - des, bottom - des,

                viewRadius, paint);

        //绘制按钮左边绿色长条遮挡

        paint.setStyle(Paint.Style.FILL);

        paint.setStrokeWidth(1);

        drawArc(canvas,

                left, top,

                left +2 *viewRadius, top +2 *viewRadius,

                90, 180, paint);

        canvas.drawRect(

left +viewRadius, top,

                viewState.buttonX, top +2 *viewRadius,

                paint);

        //绘制小线条

        if(showIndicator){

drawCheckedIndicator(canvas);

        }

//绘制按钮

        drawButton(canvas, viewState.buttonX, centerY);

    }

/**

* 绘制选中状态指示器

    * @param canvas

    */

    protected void drawCheckedIndicator(Canvas canvas) {

drawCheckedIndicator(canvas,

                viewState.checkedLineColor,

                checkLineWidth,

                left +viewRadius -checkedLineOffsetX, centerY -checkLineLength,

                left +viewRadius -checkedLineOffsetY, centerY +checkLineLength,

                paint);

    }

/**

* 绘制选中状态指示器

    * @param canvas

    * @param color

    * @param lineWidth

    * @param sx

    * @param sy

    * @param ex

    * @param ey

    * @param paint

    */

    protected void drawCheckedIndicator(Canvas canvas,

                                        int color,

                                        float lineWidth,

                                        float sx, float sy, float ex, float ey,

                                        Paint paint) {

paint.setStyle(Paint.Style.STROKE);

        paint.setColor(color);

        paint.setStrokeWidth(lineWidth);

        canvas.drawLine(

sx, sy, ex, ey,

                paint);

    }

/**

* 绘制关闭状态指示器

    * @param canvas

    */

    private void drawUncheckIndicator(Canvas canvas) {

drawUncheckIndicator(canvas,

                uncheckCircleColor,

                uncheckCircleWidth,

                right -uncheckCircleOffsetX, centerY,

                uncheckCircleRadius,

                paint);

    }

/**

* 绘制关闭状态指示器

    * @param canvas

    * @param color

    * @param lineWidth

    * @param centerX

    * @param centerY

    * @param radius

    * @param paint

    */

    protected void drawUncheckIndicator(Canvas canvas,

                                        int color,

                                        float lineWidth,

                                        float centerX, float centerY,

                                        float radius,

                                        Paint paint) {

paint.setStyle(Paint.Style.STROKE);

        paint.setColor(color);

        paint.setStrokeWidth(lineWidth);

        canvas.drawCircle(centerX, centerY, radius, paint);

    }

/**

    * @param canvas

    * @param left

    * @param top

    * @param right

    * @param bottom

    * @param startAngle

    * @param sweepAngle

    * @param paint

    */

    private void drawArc(Canvas canvas,

                        float left, float top,

                        float right, float bottom,

                        float startAngle, float sweepAngle,

                        Paint paint){

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

canvas.drawArc(left, top, right, bottom,

                    startAngle, sweepAngle, true, paint);

        }else{

rect.set(left, top, right, bottom);

            canvas.drawArc(rect,

                    startAngle, sweepAngle, true, paint);

        }

}

/**

    * @param canvas

    * @param left

    * @param top

    * @param right

    * @param bottom

    * @param backgroundRadius

    * @param paint

    */

    private void drawRoundRect(Canvas canvas,

                              float left, float top,

                              float right, float bottom,

                              float backgroundRadius,

                              Paint paint){

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

canvas.drawRoundRect(left, top, right, bottom,

                    backgroundRadius, backgroundRadius, paint);

        }else{

rect.set(left, top, right, bottom);

            canvas.drawRoundRect(rect,

                    backgroundRadius, backgroundRadius, paint);

        }

}

/**

    * @param canvas

    * @param x px

    * @param y px

*/

    private void drawButton(Canvas canvas, float x, float y) {

canvas.drawCircle(x, y, buttonRadius, buttonPaint);

        paint.setStyle(Paint.Style.STROKE);

        paint.setStrokeWidth(1);

        paint.setColor(0XffDDDDDD);

        canvas.drawCircle(x, y, buttonRadius, paint);

    }

@Override

    public void setChecked(boolean checked) {

if(checked == isChecked()){

postInvalidate();

return;

        }

toggle(enableEffect, false);

    }

@Override

    public boolean isChecked() {

return isChecked;

    }

@Override

    public void toggle() {

toggle(true);

    }

/**

* 切换状态

    * @param animate

    */

    public void toggle(boolean animate) {

toggle(animate, true);

    }

private void toggle(boolean animate, boolean broadcast) {

if(!isEnabled()){return;}

if(isEventBroadcast){

throw new RuntimeException("should NOT switch the state in method: [onCheckedChanged]!");

        }

if(!isUiInited){

isChecked = !isChecked;

            if(broadcast){

broadcastEvent();

            }

return;

        }

if(valueAnimator.isRunning()){

valueAnimator.cancel();

        }

if(!enableEffect || !animate){

isChecked = !isChecked;

            if(isChecked()){

setCheckedViewState(viewState);

            }else{

setUncheckViewState(viewState);

            }

postInvalidate();

            if(broadcast){

broadcastEvent();

            }

return;

        }

animateState =ANIMATE_STATE_SWITCH;

        beforeState.copy(viewState);

        if(isChecked()){

//切换到unchecked

            setUncheckViewState(afterState);

        }else{

setCheckedViewState(afterState);

        }

valueAnimator.start();

    }

/**

*

*/

    private void broadcastEvent() {

if(onCheckedChangeListener !=null){

isEventBroadcast =true;

            onCheckedChangeListener.onCheckedChanged(this, isChecked());

        }

isEventBroadcast =false;

    }

@Override

    public boolean onTouchEvent(MotionEvent event) {

if(!isEnabled()){return false;}

int actionMasked = event.getActionMasked();

        switch (actionMasked){

case MotionEvent.ACTION_DOWN:{

isTouchingDown =true;

                touchDownTime = System.currentTimeMillis();

                //取消准备进入拖动状态

                removeCallbacks(postPendingDrag);

                //预设100ms进入拖动状态

                postDelayed(postPendingDrag, 100);

break;

            }

case MotionEvent.ACTION_MOVE:{

float eventX = event.getX();

                if(isPendingDragState()){

//在准备进入拖动状态过程中,可以拖动按钮位置

                    float fraction = eventX / getWidth();

                    fraction = Math.max(0f, Math.min(1f, fraction));

                    viewState.buttonX =buttonMinX

                            + (buttonMaxX -buttonMinX)

* fraction;

                }else if(isDragState()){

//拖动按钮位置,同时改变对应的背景颜色

                    float fraction = eventX / getWidth();

                    fraction = Math.max(0f, Math.min(1f, fraction));

                    viewState.buttonX =buttonMinX

                            + (buttonMaxX -buttonMinX)

* fraction;

                    viewState.checkStateColor = (Integer)argbEvaluator.evaluate(

fraction,

                            uncheckColor,

                            checkedColor

                    );

                    postInvalidate();

                }

break;

            }

case MotionEvent.ACTION_UP:{

isTouchingDown =false;

                //取消准备进入拖动状态

                removeCallbacks(postPendingDrag);

                if(System.currentTimeMillis() -touchDownTime <=300){

//点击时间小于300ms,认为是点击操作

                    toggle();

                }else if(isDragState()){

//在拖动状态,计算按钮位置,设置是否切换状态

                    float eventX = event.getX();

                    float fraction = eventX / getWidth();

                    fraction = Math.max(0f, Math.min(1f, fraction));

                    boolean newCheck = fraction >.5f;

                    if(newCheck == isChecked()){

pendingCancelDragState();

                    }else{

isChecked = newCheck;

                        pendingSettleState();

                    }

}else if(isPendingDragState()){

//在准备进入拖动状态过程中,取消之,复位

                    pendingCancelDragState();

                }

break;

            }

case MotionEvent.ACTION_CANCEL:{

isTouchingDown =false;

                removeCallbacks(postPendingDrag);

                if(isPendingDragState()

|| isDragState()){

//复位

                    pendingCancelDragState();

                }

break;

            }

}

return true;

    }

/**

* 是否在动画状态

    * @return

    */

    private boolean isInAnimating(){

return animateState !=ANIMATE_STATE_NONE;

    }

/**

* 是否在进入拖动或离开拖动状态

    * @return

    */

    private boolean isPendingDragState(){

return animateState ==ANIMATE_STATE_PENDING_DRAG

                ||animateState ==ANIMATE_STATE_PENDING_RESET;

    }

/**

* 是否在手指拖动状态

    * @return

    */

    private boolean isDragState(){

return animateState ==ANIMATE_STATE_DRAGING;

    }

/**

* 设置是否启用阴影效果

    * @param shadowEffect true.启用

*/

    public void setShadowEffect(boolean shadowEffect) {

if(this.shadowEffect == shadowEffect){return;}

this.shadowEffect = shadowEffect;

        if(this.shadowEffect){

buttonPaint.setShadowLayer(

shadowRadius,

                    0, shadowOffset,

                    shadowColor);

        }else{

buttonPaint.setShadowLayer(

0,

                    0, 0,

                    0);

        }

}

public void setEnableEffect(boolean enable){

this.enableEffect = enable;

    }

/**

* 开始进入拖动状态

*/

    private void pendingDragState() {

if(isInAnimating()){return;}

if(!isTouchingDown){return;}

if(valueAnimator.isRunning()){

valueAnimator.cancel();

        }

animateState =ANIMATE_STATE_PENDING_DRAG;

        beforeState.copy(viewState);

        afterState.copy(viewState);

        if(isChecked()){

afterState.checkStateColor =checkedColor;

            afterState.buttonX =buttonMaxX;

            afterState.checkedLineColor =checkedColor;

        }else{

afterState.checkStateColor =uncheckColor;

            afterState.buttonX =buttonMinX;

            afterState.radius =viewRadius;

        }

valueAnimator.start();

    }

/**

* 取消拖动状态

*/

    private void pendingCancelDragState() {

if(isDragState() || isPendingDragState()){

if(valueAnimator.isRunning()){

valueAnimator.cancel();

            }

animateState =ANIMATE_STATE_PENDING_RESET;

            beforeState.copy(viewState);

            if(isChecked()){

setCheckedViewState(afterState);

            }else{

setUncheckViewState(afterState);

            }

valueAnimator.start();

        }

}

/**

* 动画-设置新的状态

*/

    private void pendingSettleState() {

if(valueAnimator.isRunning()){

valueAnimator.cancel();

        }

animateState =ANIMATE_STATE_PENDING_SETTLE;

        beforeState.copy(viewState);

        if(isChecked()){

setCheckedViewState(afterState);

        }else{

setUncheckViewState(afterState);

        }

valueAnimator.start();

    }

@Override

    public final void setOnClickListener(OnClickListener l) {}

@Override

    public final void setOnLongClickListener(OnLongClickListener l) {}

public void setOnCheckedChangeListener(OnCheckedChangeListener l){

onCheckedChangeListener = l;

    }

public interface OnCheckedChangeListener{

void onCheckedChanged(SwitchButton view, boolean isChecked);

    }

/*******************************************************/

    private static float dp2px(float dp){

Resources r = Resources.getSystem();

        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());

    }

private static int dp2pxInt(float dp){

return (int)dp2px(dp);

    }

private static int optInt(TypedArray typedArray,

                              int index,

                              int def) {

if(typedArray ==null){return def;}

return typedArray.getInt(index, def);

    }

private static float optPixelSize(TypedArray typedArray,

                                      int index,

                                      float def) {

if(typedArray ==null){return def;}

return typedArray.getDimension(index, def);

    }

private static int optPixelSize(TypedArray typedArray,

                                    int index,

                                    int def) {

if(typedArray ==null){return def;}

return typedArray.getDimensionPixelOffset(index, def);

    }

private static int optColor(TypedArray typedArray,

                                int index,

                                int def) {

if(typedArray ==null){return def;}

return typedArray.getColor(index, def);

    }

private static boolean optBoolean(TypedArray typedArray,

                                      int index,

                                      boolean def) {

if(typedArray ==null){return def;}

return typedArray.getBoolean(index, def);

    }

/*******************************************************/

/**

* 阴影半径

*/

    private int shadowRadius;

    /**

* 阴影Y偏移px

*/

    private int shadowOffset;

    /**

* 阴影颜色

*/

    private int shadowColor ;

    /**

* 背景半径

*/

    private float viewRadius;

    /**

* 按钮半径

*/

    private float buttonRadius;

    /**

* 背景高

*/

    private float height ;

    /**

* 背景宽

*/

    private float width;

    /**

* 背景位置

*/

    private float left  ;

    private float top    ;

    private float right  ;

    private float bottom ;

    private float centerX;

    private float centerY;

    /**

* 背景底色

*/

    private int background;

    /**

* 背景关闭颜色

*/

    private int uncheckColor;

    /**

* 背景打开颜色

*/

    private int checkedColor;

    /**

* 边框宽度px

*/

    private int borderWidth;

    /**

* 打开指示线颜色

*/

    private int checkLineColor;

    /**

* 打开指示线宽

*/

    private int checkLineWidth;

    /**

* 打开指示线长

*/

    private float checkLineLength;

    /**

* 关闭圆圈颜色

*/

    private int uncheckCircleColor;

    /**

*关闭圆圈线宽

*/

    private int uncheckCircleWidth;

    /**

*关闭圆圈位移X

*/

    private float uncheckCircleOffsetX;

    /**

*关闭圆圈半径

*/

    private float uncheckCircleRadius;

    /**

*打开指示线位移X

*/

    private float checkedLineOffsetX;

    /**

*打开指示线位移Y

*/

    private float checkedLineOffsetY;

    /**

* 按钮最左边

*/

    private float buttonMinX;

    /**

* 按钮最右边

*/

    private float buttonMaxX;

    /**

* 按钮画笔

*/

    private PaintbuttonPaint;

    /**

* 背景画笔

*/

    private Paintpaint;

    /**

* 当前状态

*/

    private ViewStateviewState;

    private ViewStatebeforeState;

    private ViewStateafterState;

    private RectFrect =new RectF();

    /**

* 动画状态

*/

    private int animateState =ANIMATE_STATE_NONE;

    /**

*

*/

    private ValueAnimatorvalueAnimator;

    private final android.animation.ArgbEvaluatorargbEvaluator

            =new android.animation.ArgbEvaluator();

    /**

*是否选中

*/

    private boolean isChecked;

    /**

* 是否启用动画

*/

    private boolean enableEffect;

    /**

* 是否启用阴影效果

*/

    private boolean shadowEffect;

    /**

* 是否显示指示器

*/

    private boolean showIndicator;

    /**

* 收拾是否按下

*/

    private boolean isTouchingDown =false;

    /**

*

*/

    private boolean isUiInited =false;

    /**

*

*/

    private boolean isEventBroadcast =false;

    private OnCheckedChangeListeneronCheckedChangeListener;

    /**

* 手势按下的时刻

*/

    private long touchDownTime;

    private RunnablepostPendingDrag =new Runnable() {

@Override

        public void run() {

if(!isInAnimating()){

pendingDragState();

            }

}

};

    private ValueAnimator.AnimatorUpdateListeneranimatorUpdateListener

            =new ValueAnimator.AnimatorUpdateListener() {

@Override

        public void onAnimationUpdate(ValueAnimator animation) {

float value = (Float) animation.getAnimatedValue();

            switch (animateState) {

case ANIMATE_STATE_PENDING_SETTLE: {

}

case ANIMATE_STATE_PENDING_RESET: {

}

case ANIMATE_STATE_PENDING_DRAG: {

viewState.checkedLineColor = (Integer) (argbEvaluator.evaluate(

value,

                            beforeState.checkedLineColor,

                            afterState.checkedLineColor

                    ));

                    viewState.radius =beforeState.radius

                            + (afterState.radius -beforeState.radius) * value;

                    if(animateState !=ANIMATE_STATE_PENDING_DRAG){

viewState.buttonX =beforeState.buttonX

                                + (afterState.buttonX -beforeState.buttonX) * value;

                    }

viewState.checkStateColor = (Integer)argbEvaluator.evaluate(

value,

                            beforeState.checkStateColor,

                            afterState.checkStateColor

                    );

break;

                }

case ANIMATE_STATE_SWITCH: {

viewState.buttonX =beforeState.buttonX

                            + (afterState.buttonX -beforeState.buttonX) * value;

                    float fraction = (viewState.buttonX -buttonMinX) / (buttonMaxX -buttonMinX);

                    viewState.checkStateColor = (Integer)argbEvaluator.evaluate(

fraction,

                            uncheckColor,

                            checkedColor

                    );

                    viewState.radius = fraction *viewRadius;

                    viewState.checkedLineColor = (Integer)argbEvaluator.evaluate(

fraction,

                            Color.TRANSPARENT,

                            checkLineColor

                    );

break;

                }

default:

case ANIMATE_STATE_DRAGING: {

}

case ANIMATE_STATE_NONE: {

break;

                }

}

postInvalidate();

        }

};

    private Animator.AnimatorListeneranimatorListener

            =new Animator.AnimatorListener() {

@Override

        public void onAnimationStart(Animator animation) {

}

@Override

        public void onAnimationEnd(Animator animation) {

switch (animateState) {

case ANIMATE_STATE_DRAGING: {

break;

                }

case ANIMATE_STATE_PENDING_DRAG: {

animateState =ANIMATE_STATE_DRAGING;

                    viewState.checkedLineColor = Color.TRANSPARENT;

                    viewState.radius =viewRadius;

                    postInvalidate();

break;

                }

case ANIMATE_STATE_PENDING_RESET: {

animateState =ANIMATE_STATE_NONE;

                    postInvalidate();

break;

                }

case ANIMATE_STATE_PENDING_SETTLE: {

animateState =ANIMATE_STATE_NONE;

                    postInvalidate();

                    broadcastEvent();

break;

                }

case ANIMATE_STATE_SWITCH: {

isChecked = !isChecked;

                    animateState =ANIMATE_STATE_NONE;

                    postInvalidate();

                    broadcastEvent();

break;

                }

default:

case ANIMATE_STATE_NONE: {

break;

                }

}

}

@Override

        public void onAnimationCancel(Animator animation) {

}

@Override

        public void onAnimationRepeat(Animator animation) {

}

};

    /*******************************************************/

/**

* 保存动画状态

* */

    private static class ViewState {

/**

* 按钮x位置[buttonMinX-buttonMaxX]

*/

        float buttonX;

        /**

* 状态背景颜色

*/

        int checkStateColor;

        /**

* 选中线的颜色

*/

        int checkedLineColor;

        /**

* 状态背景的半径

*/

        float radius;

        ViewState(){}

private void copy(ViewState source){

this.buttonX = source.buttonX;

            this.checkStateColor = source.checkStateColor;

            this.checkedLineColor = source.checkedLineColor;

            this.radius = source.radius;

        }

}

}

2,新建switch_button_attrs.xml

<declare-styleable name="SwitchButton">

    <attr name="sb_shadow_radius" format="reference|dimension" />

    <attr name="sb_shadow_offset" format="reference|dimension" />

    <attr name="sb_shadow_color" format="reference|color" />

    <attr name="sb_uncheck_color" format="reference|color" />

    <attr name="sb_checked_color" format="reference|color" />

    <attr name="sb_border_width" format="reference|dimension" />

    <attr name="sb_checkline_color" format="reference|color" />

    <attr name="sb_checkline_width" format="reference|dimension" />

    <attr name="sb_uncheckcircle_color" format="reference|color" />

    <attr name="sb_uncheckcircle_width" format="reference|dimension" />

    <attr name="sb_uncheckcircle_radius" format="reference|dimension" />

    <attr name="sb_checked" format="reference|boolean" />

    <attr name="sb_shadow_effect" format="reference|boolean" />

    <attr name="sb_effect_duration" format="reference|integer" />

    <attr name="sb_button_color" format="reference|color" />

    <attr name="sb_show_indicator" format="reference|boolean" />

    <attr name="sb_background" format="reference|color" />

    <attr name="sb_enable_effect" format="reference|boolean" />

</declare-styleable>

3.xml中使用

<*****SwitchButton

    android:id="@+id/sb_xxtz"

    android:layout_width="50dp"

    android:layout_height="30dp"

    app:sb_checked="true"

    app:sb_show_indicator="false"

    app:sb_uncheck_color="#fff"//未选中颜色

    app:sb_checked_color="#FFF8B702"//选中颜色

    android:layout_alignParentTop="true"

    android:layout_alignParentEnd="true"/>

这样就OK了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,907评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,546评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,705评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,624评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,940评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,371评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,672评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,396评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,069评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,350评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,876评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,243评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,847评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,004评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,755评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,378评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,266评论 2 259

推荐阅读更多精彩内容