Android(安卓)双向拖动控件(类似 SeekBar)
16lz
2021-12-04
自定义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 的颜色值即可
效果图:
源码下载
更多相关文章
- 迁移到Androidx的常用依赖映射
- android 移送控件
- android之RecycleView适配器添加点击事件
- android点击实现图片放大缩小
- Android分页控件xlistview
- android中popupwindow的点滴
- ImageView
- Android圆形图片--自定义控件
- android基础控件(3)BottomNavigationView+FragmentLayout实现底层