Android-自定义滑动按钮

来源:互联网 发布:淘宝圈椅三件套 编辑:程序博客网 时间:2024/06/06 02:22

效果图:


layout布局:

<com.doudoubird.droidzou.newflashlightrevision.widget.SwitchVerticalSlide            android:id="@+id/control"            android:layout_centerHorizontal="true"            android:layout_marginTop="40dp"            android:layout_below="@id/background_four"            android:layout_width="wrap_content"            android:layout_height="wrap_content">            <ImageView                android:src="@mipmap/track_off"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />            <ImageView                android:src="@mipmap/track_button_close"                android:layout_gravity="bottom"                android:layout_width="wrap_content"                android:layout_height="wrap_content" /></com.doudoubird.droidzou.newflashlightrevision.widget.SwitchVerticalSlide>

自定义SwitchVerticalSlide:

public class SwitchVerticalSlide extends FrameLayout {    private SwitchSlideListener slideListener;    private Context mContext;    public SwitchVerticalSlide(Context context) {        this(context,null);    }    public SwitchVerticalSlide(Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    public SwitchVerticalSlide(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mContext=context;    }    public void addSlideListener(SwitchSlideListener slideListener){        this.slideListener=slideListener;    }    private static final int maxSlideInterval=15;//点击时在垂直方向可抖动的误差    private float downP;    private float trackHeight;    private float trackButtonWidth;    private float trackButtonHeight;    private float downX;    private float downY;    private boolean trackLocation=true;    private boolean antiShakeFlag;//抗抖动,用于处理点击事件    private boolean isFirstDownLoad;    private View child0;    private View child1;    private float orbitalTransferLength;//滑动时改变按钮状态的滑动距离    private boolean onFinishInflateFlag;    private int onFinishInflateState;//1:打开状态,2:关闭状态    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        if (!isFirstDownLoad){            trackHeight=getChildAt(0).getMeasuredHeight();            trackButtonWidth=getChildAt(1).getMeasuredWidth();            trackButtonHeight=getChildAt(1).getMeasuredHeight();            child0=getChildAt(0);            child1=getChildAt(1);            isFirstDownLoad=true;            orbitalTransferLength=trackHeight/5.0f;        }    }    public void onResumeFinishInflate() {        if (onFinishInflateFlag){            switch (onFinishInflateState) {                case 1:                    openSwitch();                    onFinishInflateState=0;                    break;                case 2:                    closeSwitch();                    onFinishInflateState=0;                    break;            }            onFinishInflateFlag=false;        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                antiShakeFlag=false;                downP=event.getRawY();                downX=event.getX();                downY=event.getY();                break;            case MotionEvent.ACTION_MOVE:                if (trackLocation){                    float dValue = event.getRawY() - downP;                    if(isInTrackButton(downX,downY, true)){                        if (dValue<0){                            if(-dValue>orbitalTransferLength){                                ((ImageView) child1).setImageResource(R.mipmap.track_button_open);                                ((ImageView) child0).setImageResource(R.mipmap.track_on);                            }else {                                ((ImageView) child1).setImageResource(R.mipmap.track_button_close);                                ((ImageView) child0).setImageResource(R.mipmap.track_off);                            }                            //抗抖动                            if (antiShakeFlag|dValue<-maxSlideInterval){                                //在按下点之向上滑动                                antiShakeFlag=true;                                float maxValue = trackButtonHeight - trackHeight;                                if (dValue> maxValue){                                    child1.setTranslationY(dValue);                                }else {                                    child1.setTranslationY(maxValue);                                }                            }                        }else {                            if (dValue>maxSlideInterval){                                antiShakeFlag=true;                            }                            child1.setTranslationY(0);                        }                    }else{                        //如果在这个区域内,垂直方向超过了10,则需要改变 antiShakeFlag 取消点击                        if (Math.abs(dValue)>maxSlideInterval){                            antiShakeFlag=true;                        }                    }                }else {                    float dValue = event.getRawY() - downP;                    if (isInTrackButton(downX,downY,false)){                        if (dValue>0){                            if(dValue>orbitalTransferLength){                                ((ImageView) child1).setImageResource(R.mipmap.track_button_close);                                ((ImageView) child0).setImageResource(R.mipmap.track_off);                            }else {                                ((ImageView) child1).setImageResource(R.mipmap.track_button_open);                                ((ImageView) child0).setImageResource(R.mipmap.track_on);                            }                            if (antiShakeFlag|dValue>maxSlideInterval){                                //在按下点之下滑动                                antiShakeFlag=true;                                float maxValue = trackButtonHeight - trackHeight + dValue;                                if (maxValue<0){                                    child1.setTranslationY(maxValue);                                }else {                                    child1.setTranslationY(0);                                }                            }                        }else {                            if (dValue<-maxSlideInterval){                                antiShakeFlag=true;                            }                            child1.setTranslationY(trackButtonHeight-trackHeight);                        }                    }else {                        if (Math.abs(dValue)>maxSlideInterval){                            antiShakeFlag=true;                        }                    }                }                break;            case MotionEvent.ACTION_UP:                if (!antiShakeFlag){                    //第一次按下滑动距离不超过20,视为点击                    if (trackLocation){                        ((ImageView) child1).setImageResource(R.mipmap.track_button_open);                        ((ImageView) child0).setImageResource(R.mipmap.track_on);                        getChildAt(1).setTranslationY(trackButtonHeight-trackHeight);                        trackLocation=false;                        slideListener.onSwitchSlide(true);                    }else {                        ((ImageView) child1).setImageResource(R.mipmap.track_button_close);                        ((ImageView) child0).setImageResource(R.mipmap.track_off);                        child1.setTranslationY(0);                        trackLocation=true;                        slideListener.onSwitchSlide(false);                    }                }else {                    if (trackLocation){                        if(isInTrackButton(downX,downY, true)){                            if((downP-event.getRawY())>orbitalTransferLength){                                //打开开关                                trackLocation=false;                                child1.setTranslationY(trackButtonHeight-trackHeight);                                slideListener.onSwitchSlide(true);                            }else {                                child1.setTranslationY(0);                            }                        }                    }else{                        if(isInTrackButton(downX,downY, false)){                            if((event.getRawY()-downP)>orbitalTransferLength){                                //关闭开关                                trackLocation=true;                                child1.setTranslationY(0);                                slideListener.onSwitchSlide(false);                            }else {                                child1.setTranslationY(trackButtonHeight-trackHeight);                            }                        }                    }                }                break;        }        return true;    }    public void openSwitch(){        if (child0!=null&&child1!=null) {            ((ImageView) child1).setImageResource(R.mipmap.track_button_open);            ((ImageView) child0).setImageResource(R.mipmap.track_on);            child1.setTranslationY(trackButtonHeight-trackHeight);            trackLocation=false;        }else {            onFinishInflateFlag=true;//完成加载后改变状态            onFinishInflateState=1;        }    }    public void closeSwitch(){        if (child0!=null&&child1!=null) {            ((ImageView) child1).setImageResource(R.mipmap.track_button_close);            ((ImageView) child0).setImageResource(R.mipmap.track_off);            child1.setTranslationY(0);            trackLocation=true;        }else {            onFinishInflateFlag=true;//完成加载后改变状态            onFinishInflateState=2;        }    }    /**     *     * @param downX     * @param downY     * @param down true表示按钮在下面,false表示按钮在上面     * @return true 在矩形内,false 不在矩形内     */    private boolean isInTrackButton(float downX,float downY,boolean down){        float leftUpX=0.0f;        float rightDownX=trackButtonWidth;        float leftUpY;        float rightDownY;        if (down){            leftUpY=trackHeight-trackButtonHeight;            rightDownY=trackHeight;        }else {            leftUpY=0;            rightDownY=trackButtonHeight;        }        return downY >= leftUpY && downY <= rightDownY && downX >= leftUpX && downX <= rightDownX;    }}

其用到的接口SwitchSlideListener:

public interface SwitchSlideListener {    /**     *     * @param switchFlag true表示按钮打开,false表示按钮关闭     */    void onSwitchSlide(boolean switchFlag);}

onCreate处理回调结果(相当于用法):

((SwitchVerticalSlide) findViewById(R.id.control)).addSlideListener(new SwitchSlideListener() {            @Override            public void onSwitchSlide(boolean switchFlag) {                if (switchFlag){                    Toast.makeText(MainActivity.this, "打开", Toast.LENGTH_SHORT).show();                }else {                    Toast.makeText(MainActivity.this, "关闭", Toast.LENGTH_SHORT).show();                }            }});

本人亲测有效,完全属于个人原创,没有参考任何人的代码

原创粉丝点击