Android-自定义滑动按钮

效果图:


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();
                }
            }
});

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值