一个简单的拖动条,类似ruler,先上图
演示用,所以很多细节如自定义属性,惯性滑动等没做,直接上代码,有注释:
public class RegulateView extends View {
private int radius_normal = DensityUtil.dp2px(2);//大圆半径
private int radius_big = DensityUtil.dp2px(3);//小圆半径
private Paint mPaint;//小圆画笔
private Paint pink_paint;//大圆画笔
private int gap = radius_normal * 5;//间距
private int itemCount = 100;//刻度
private int w, h;
private float startX;//起始绘制坐标x
private float startY;//起始绘制坐标y
private Paint mTextPaint;//text
public RegulateView(Context context) {
this(context, null);
}
public RegulateView(Context context, @androidx.annotation.Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RegulateView(Context context, @androidx.annotation.Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setProgress(float index) {
this.index = index;
startX = centerX - (index + itemCount) * gap;
invalidate();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
pink_paint = new Paint();
pink_paint.setColor(Color.RED);
pink_paint.setAntiAlias(true);
pink_paint.setDither(true);
mTextPaint = new Paint();
mTextPaint.setTextSize(DensityUtil.dp2px(10));
mTextPaint.setColor(Color.RED);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
width = getMeasuredWidth() * 3 / 4 - getPaddingLeft() - getPaddingRight();
}
if (heightMode != MeasureSpec.EXACTLY) {
height = DensityUtil.dp2px(5) * 8;
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float start = startX;
for (int i = -itemCount; i <= itemCount; i++) {
if (i % 5 == 0) {
//给一个范围,屏幕中心点设为选中点
if (start < centerX + (float) gap / 2 && start > centerX - (float) gap / 2) {
canvas.drawCircle(start, startY, radius_big, pink_paint);
} else
canvas.drawCircle(start, startY, radius_big, mPaint);
} else {
if (start < centerX + (float) gap / 2 && start > centerX - (float) gap / 2) {
canvas.drawCircle(start, startY, radius_normal, pink_paint);
} else
canvas.drawCircle(start, startY, radius_normal, mPaint);
}
start += gap;
}
canvas.drawText((int)index + "%", centerX, startY - radius_big*2, mTextPaint);
}
float index;
float lastX;
float centerX;
float centerY;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = event.getX();
break;
case MotionEvent.ACTION_MOVE:
float swipeDistance = event.getX() - lastX;
startX += swipeDistance;
//限制右边界
if (startX <= w / 2 - itemCount * gap * 2) {
startX = centerX - itemCount * gap * 2;
}
//限制滚动左边界
if (startX >= w / 2) {
startX = centerX;
}
index = (centerX - startX - itemCount * gap) / gap;
int progress = floatToInt(index);
if (mListener != null)
mListener.onScroll(progress);
lastX = event.getX();
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.w = w;
this.h = h;
centerX = (float) w / 2;
centerY = (float) h / 2 + radius_big*2;
startX = centerX - itemCount * gap;
startY = centerY;
}
private onProgressScrollListener mListener;
public onProgressScrollListener getListener() {
return mListener;
}
public void setListener(onProgressScrollListener listener) {
mListener = listener;
}
public interface onProgressScrollListener {
void onScroll(int index);
}
//四舍五入
private int floatToInt(float f) {
int i = 0;
if (f > 0)
i = (int) ((f * 10 + 5) / 10);
else if (f < 0)
i = (int) ((f * 10 - 5) / 10);
else i = 0;
return i;
}
}