Android 双向拖动控件(类似 SeekBar)

自定义view:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class DoubleSeekBar extends View {


    private float rightRectRightBottomX;
    private float rightRectRightTopX;
    private float rightRectLeftBottomX;
    private float rightRectLeftTopX;
    private Paint rightRectPaint;

    private float leftRectRightBottomX;
    private float leftRectRightTopX;
    private float leftRectLeftBottomX;
    private float leftRectLeftTopX;
    private Paint leftRectPaint;

    private Paint bgLinePaint;
    private Paint fgLinePaint;
    private DoubleSeekBar doubleSeekBar;

    private Context context;
    private int[] parentLocation=new int[2];
    private String TAG = "DoubleSeekBar";
    private boolean isFirst=true;


    private OnSlideChangeListener onSlideChangeListener;
    public interface OnSlideChangeListener{
        void onMiddleSectionChange(float percent);
        void onLeftSlideChange(float percent);
        void onRightSlideChange(float percent);
    }

    public void setOnSlideChangeListener(OnSlideChangeListener onSlideChangeListener){
        this.onSlideChangeListener=onSlideChangeListener;
    }

    public DoubleSeekBar(Context context) {
        super(context);
        this.context=context;
        this.doubleSeekBar =this;
        LogTools.i(TAG,"c1");
    }

    public DoubleSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        LogTools.i(TAG,"c2");
        this.context=context;
        this.doubleSeekBar =this;

        bgLinePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        bgLinePaint.setColor(ContextCompat.getColor(context,R.color.deep_gray));
        bgLinePaint.setStrokeWidth(DpTools.dp2px(context,3f));

        fgLinePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        fgLinePaint.setColor(ContextCompat.getColor(context,R.color.colorPrimary));
        fgLinePaint.setStrokeWidth(DpTools.dp2px(context,3f));

        leftRectPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        leftRectPaint.setColor(ContextCompat.getColor(context,R.color.colorPrimary));
        leftRectPaint.setStrokeWidth(DpTools.dp2px(context,1f));

        leftRectLeftTopX=0f;
        leftRectLeftBottomX=0f;
        leftRectRightTopX=DpTools.dp2pxF(context,18f);
        leftRectRightBottomX=DpTools.dp2pxF(context,18f);

        rightRectPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        rightRectPaint.setColor(ContextCompat.getColor(context,R.color.colorPrimary));
        rightRectPaint.setStrokeWidth(DpTools.dp2px(context,1f));
    }


    private float dis;
    private float downX=0,downY=0;
    private boolean isLeftRectTouch=false;
    private boolean isRightRectTouch=false;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        LogTools.i(TAG,"onDraw=");

        if(isFirst){
            rightRectLeftTopX=getMeasuredWidth()-DpTools.dp2pxF(context,18f);
            rightRectLeftBottomX=getMeasuredWidth()-DpTools.dp2pxF(context,18f);
            rightRectRightTopX=getMeasuredWidth();
            rightRectRightBottomX=getMeasuredWidth();

            getRootView().setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {

                    getLocationInWindow(parentLocation);
                    int vW=getMeasuredWidth();
                    int vH=getMeasuredHeight();

                    switch (event.getAction()){
                        case MotionEvent.ACTION_DOWN:
                            downX= event.getRawX();
                            downY= event.getRawY();
                            isLeftRectTouch=isLeftRectTouch(downX,downY,parentLocation[0],parentLocation[1]);
                            isRightRectTouch=isRightRectTouch(downX,downY,parentLocation[0],parentLocation[1]);
                            LogTools.i(TAG,"down=x="+downX+",y="+downY);
                            break;
                        case MotionEvent.ACTION_MOVE:
                            float moveX=event.getRawX();
                            float moveY=event.getRawY();

                            if(isLeftRectTouch && !isRightRectTouch){
                                dis = moveX-downX;
                                if(leftRectRightTopX+dis >= DpTools.dp2pxF(context,18f) && leftRectRightTopX+dis <= getMeasuredWidth()-DpTools.dp2pxF(context,18f)){
                                    if(leftRectRightTopX+dis < rightRectLeftTopX){

                                        leftRectLeftTopX=leftRectLeftTopX+dis;
                                        leftRectLeftBottomX=leftRectLeftBottomX+dis;
                                        leftRectRightTopX=leftRectRightTopX+dis;
                                        leftRectRightBottomX=leftRectRightBottomX+dis;
                                        doubleSeekBar.invalidate();
                                        downX=moveX;

                                        LogTools.i(TAG,"invalidateLeft=dis="+dis+
                                                ",leftRectLeftTopX="+leftRectLeftTopX+",leftRectLeftBottomX="+leftRectLeftBottomX+
                                                ",leftRectRightTopX="+leftRectRightTopX+",leftRectRightBottomX="+leftRectRightBottomX+
                                                ",cx=="+DpTools.dp2pxF(context,18+18f)+",gmw="+getMeasuredWidth());

                                        if(onSlideChangeListener!=null){
                                            float slideLength=getMeasuredWidth()-DpTools.dp2pxF(context,18+18f);
                                            float centerLength=(rightRectLeftTopX-DpTools.dp2pxF(context,18f))-(leftRectRightTopX-DpTools.dp2pxF(context,18f));
                                            float centerPercent=centerLength/slideLength;
                                            float leftPercent=(leftRectRightTopX-DpTools.dp2pxF(context,18f))/slideLength;
                                            float rightPercent=(rightRectLeftTopX-DpTools.dp2pxF(context,18f))/slideLength;
                                            onSlideChangeListener.onMiddleSectionChange(centerPercent);
                                            onSlideChangeListener.onLeftSlideChange(leftPercent);
                                           
                                            LogTools.i(TAG,"slideLength="+slideLength+",centerLength="+centerLength+",centerPercent="+centerPercent+",leftPercent="+leftPercent+",rightPercent="+rightPercent);
                                        }
                                    }
                                }
                            }

                            if(isRightRectTouch && !isLeftRectTouch){
                                dis = moveX-downX;
                                if(rightRectLeftTopX+dis >= DpTools.dp2pxF(context,18f) && rightRectLeftTopX+dis <= getMeasuredWidth()-DpTools.dp2pxF(context,18f)){
                                    if(rightRectLeftTopX+dis > leftRectRightTopX){

                                        rightRectLeftTopX=rightRectLeftTopX+dis;
                                        rightRectLeftBottomX=rightRectLeftBottomX+dis;
                                        rightRectRightTopX=rightRectRightTopX+dis;
                                        rightRectRightBottomX=rightRectRightBottomX+dis;
                                        doubleSeekBar.invalidate();
                                        downX=moveX;

                                        LogTools.i(TAG,"invalidateLeft=dis="+dis+
                                                ",rightRectLeftTopX="+rightRectLeftTopX+",rightRectLeftBottomX="+rightRectLeftBottomX+
                                                ",rightRectRightTopX="+rightRectRightTopX+",rightRectRightBottomX="+rightRectRightBottomX+
                                                ",cx=="+DpTools.dp2pxF(context,18+18f)+",gmw="+getMeasuredWidth());

                                        if(onSlideChangeListener!=null){
                                            float slideLength=getMeasuredWidth()-DpTools.dp2pxF(context,18+18f);
                                            float centerLength=(rightRectLeftTopX-DpTools.dp2pxF(context,18f))-(leftRectRightTopX-DpTools.dp2pxF(context,18f));
                                            float centerPercent=centerLength/slideLength;
                                            float leftPercent=(leftRectRightTopX-DpTools.dp2pxF(context,18f))/slideLength;
                                            float rightPercent=(rightRectLeftTopX-DpTools.dp2pxF(context,18f))/slideLength;
                                            onSlideChangeListener.onMiddleSectionChange(centerPercent);
                                           
                                            onSlideChangeListener.onRightSlideChange(rightPercent);
                                            LogTools.i(TAG,"slideLength="+slideLength+",centerLength="+centerLength+",centerPercent="+centerPercent+",leftPercent="+leftPercent+",rightPercent="+rightPercent);
                                        }
                                    }
                                }
                            }


                            LogTools.i(TAG,"move=x="+moveX+",y="+moveY+",down=---x="+downX+",y----="+downY);
                            break;
                        case MotionEvent.ACTION_UP:
                            isLeftRectTouch=false;
                            isRightRectTouch=false;
                            float upX=event.getRawX();
                            float upY=event.getRawY();
                            LogTools.i(TAG,"up=x="+upX+",y="+upY);
                            break;
                    }

                    LogTools.i(TAG,"getRootView="+",ll=w="+parentLocation[0]+",ll=h="+parentLocation[1]+",vW="+vW+",vH="+vH+",dp2px="+DpTools.dp2pxF(context,50));
                    return false;
                }
            });

            isFirst=false;
        }


        canvas.drawLine(DpTools.dp2pxF(context,18f),0 ,getMeasuredWidth()-DpTools.dp2pxF(context,18f),0,fgLinePaint);//前景
        canvas.drawLine(DpTools.dp2pxF(context,18f),0 ,leftRectRightTopX,0,bgLinePaint);//左边背景
        canvas.drawLine(getMeasuredWidth()-DpTools.dp2pxF(context,18f),0 ,rightRectLeftTopX,0,bgLinePaint);//右边背景

        //左边拖到控件
        Path leftPath=new Path();
        leftPath.moveTo(leftRectRightTopX, DpTools.dp2px(context,3f));
        leftPath.lineTo(leftRectLeftTopX, DpTools.dp2pxF(context,17.5f));
        leftPath.lineTo(leftRectLeftBottomX, DpTools.dp2pxF(context,32f+3f));
        leftPath.lineTo(leftRectRightBottomX, DpTools.dp2pxF(context,32f+3f));
        leftPath.close();//封闭
        canvas.drawPath(leftPath, leftRectPaint);

        //右边边拖到控件
        Path rightPath=new Path();
        rightPath.moveTo(rightRectLeftTopX, DpTools.dp2px(context,3f));
        rightPath.lineTo(rightRectRightTopX, DpTools.dp2pxF(context,17.5f));
        rightPath.lineTo(rightRectRightBottomX, DpTools.dp2pxF(context,32f+3f));
        rightPath.lineTo(rightRectLeftBottomX, DpTools.dp2pxF(context,32f+3f));
        rightPath.close();//封闭
        canvas.drawPath(rightPath, rightRectPaint);
    }

    //判断是否点击的是左边拖到控件
    private boolean isLeftRectTouch(float downX,float downY,int parentLW,int parentLH){
        float leftX=leftRectLeftTopX+parentLW-100;
        float rightX=leftRectRightTopX+parentLW;

        float topY=parentLH+DpTools.dp2pxF(context,3f);
        float bottomY=parentLH+DpTools.dp2pxF(context,3f)+DpTools.dp2pxF(context,32f)+100;
        LogTools.i(TAG,"leftX="+leftX+",rightX="+rightX+",topY="+topY+",bottomY="+bottomY);
        if(downX>=leftX &&
                downX<= rightX &&
                downY> topY &&
                downY<=bottomY){
            LogTools.i(TAG,"点击left");
            return true;
        }else{
            return false;
        }
    }

    //判断是否点击的是右边拖到控件
    private boolean isRightRectTouch(float downX,float downY,int parentLW,int parentLH){
        float leftX=rightRectLeftTopX;
        float rightX=rightRectRightTopX+100;

        float topY=parentLH+DpTools.dp2pxF(context,3f);
        float bottomY=parentLH+DpTools.dp2pxF(context,3f)+DpTools.dp2pxF(context,32f)+100;
        LogTools.i(TAG,"leftX="+leftX+",rightX="+rightX+",topY="+topY+",bottomY="+bottomY);
        if(downX>=leftX &&
                downX<= rightX &&
                downY> topY &&
                downY<=bottomY){
            LogTools.i(TAG,"点击right");
            return true;
        }else{
            return false;
        }
    }



//    @Override
//    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//        super.onLayout(changed, left, top, right, bottom);
//
//        LogTools.i(TAG,"onLayout="+changed);
//    }
//
//    @Override
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        LogTools.i(TAG,"onMeasure=w="+widthMeasureSpec+",h="+heightMeasureSpec);
//    }

}

工具类: 


public class DpTools {

    public static float dp2pxF(Context context, float dpValue){
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpValue,context.getResources().getDisplayMetrics());
    }
}

布局文件:


            

最后替换自定义view 的颜色值即可

效果图:

Android 双向拖动控件(类似 SeekBar)_第1张图片

源码下载

 

你可能感兴趣的:(android,seekbar)