项目需要做了一个正负滑动的Seekbar
public class CenterSeekBarView extends View {
private static final String TAG = CenterSeekBarView.class.getSimpleName();
private Paint mThumbPaint;
private Paint mProgressPaint;
private Paint mTextPaint;
private Paint mThumbTextPaint;
@ColorInt
private int progressBackColor;
@ColorInt
private int progressColor;
private int maxValue;
private int minValue;
private int measuredWidth;
private int measuredHeight;
private float thumbRadius;
private int progressBarCoarse;
private int viewPadding;
private final float[] thumbPosition = new float[2];
private float lastX;
private float lastY;
private boolean canMove;
public CenterSeekBarView(Context context) {
this(context, null);
init();
}
public CenterSeekBarView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init();
}
public CenterSeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mThumbPaint = new Paint();
mThumbPaint.setAntiAlias(true);
mThumbPaint.setStyle(Paint.Style.FILL);
mThumbPaint.setColor(Color.parseColor("#303030"));
mProgressPaint = new Paint();
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStyle(Paint.Style.FILL);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(Color.parseColor("#FFFFFF"));
mThumbTextPaint = new Paint();
mThumbTextPaint.setAntiAlias(true);
mThumbTextPaint.setStyle(Paint.Style.FILL);
mThumbTextPaint.setColor(Color.parseColor("#FFFFFF"));
progressBackColor = Color.parseColor("#C2C2C2");
progressColor = Color.parseColor("#C79C5B");
thumbRadius = dip2px(20);
progressBarCoarse = dip2px(10);
viewPadding = dip2px(40);
maxValue = 10;
minValue = -10;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
measuredWidth = getMeasuredWidth();
measuredHeight = getMeasuredHeight();
float x = measuredWidth / 2f;
float y = measuredHeight / 2f;
thumbPosition[0] = x;
thumbPosition[1] = y;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawProgressBackground(canvas);
drawProgressBar(canvas);
drawThumb(canvas);
drawText(canvas);
}
private void drawProgressBar(Canvas canvas) {
float left = measuredWidth / 2f;
float top = measuredHeight / 2f - progressBarCoarse / 2f;
float right = thumbPosition[0];
float bottom = measuredHeight / 2f + progressBarCoarse / 2f;
mProgressPaint.setColor(progressColor);
canvas.drawRoundRect(left, top, right, bottom, 5, 5, mProgressPaint);
}
private void drawProgressBackground(Canvas canvas) {
float left = viewPadding;
float top = measuredHeight / 2f - progressBarCoarse / 2f;
float right = measuredWidth - viewPadding;
float bottom = measuredHeight / 2f + progressBarCoarse / 2f;
mProgressPaint.setColor(progressBackColor);
canvas.drawRoundRect(left, top, right, bottom, 5, 5, mProgressPaint);
}
private void drawThumb(Canvas canvas) {
canvas.drawCircle(thumbPosition[0], thumbPosition[1], thumbRadius, mThumbPaint);
mThumbTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(getPercent(), thumbPosition[0], thumbPosition[1] - thumbRadius - dip2px(10), mThumbTextPaint);
}
private void drawText(Canvas canvas) {
float y = measuredHeight / 2f + progressBarCoarse / 2f + dip2px(20);
mTextPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(minValue + "km/h", viewPadding, y, mTextPaint);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(maxValue + "km/h", measuredWidth - viewPadding, y, mTextPaint);
}
private String getPercent() {
float total = measuredWidth / 2f - viewPadding;
float current = Math.abs(thumbPosition[0] - measuredWidth / 2f);
float percent = current / total;
Log.d(TAG, "getPercent: " + total + "," + current + "<" + percent);
if (thumbPosition[0] < measuredWidth / 2f) {
return "" + (int) (percent * minValue);
}
return (int) (percent * maxValue) + "";
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
Log.d(TAG, "onTouchEvent: enable false");
return false;
}
int x = (int) event.getRawX();
int y = (int) event.getRawY();
float px = event.getX();
float py = event.getY();
int dealtX = 0;
int dealtY = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(true);
canMove = checkInThumb(px, py);
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "onTouchEvent: move");
dealtX += Math.abs(x - lastX);
dealtY += Math.abs(y - lastY);
// 这里是拦截判断依据是左右上下滑动,水平进行滑动,自己消费,请求父类ViewPage不拦截;竖直方向滑动,交给父类Scrollview
getParent().requestDisallowInterceptTouchEvent(dealtX >= dealtY);
lastX = x;
lastY = y;
setMovePosition(px);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
Log.d(TAG, "onTouchEvent: up");
canMove = false;
setMovePosition(px);
getParent().requestDisallowInterceptTouchEvent(false);
break;
default:
break;
}
return true;
}
private void setMovePosition(float px) {
if (px > measuredWidth - viewPadding) {
px = measuredWidth - viewPadding;
} else if (px < viewPadding) {
px = viewPadding;
}
// float tempX = checkIntPosition(px);
// if (tempX > measuredWidth - viewPadding) {
// tempX = measuredWidth - viewPadding;
// } else if (tempX < viewPadding) {
// tempX = viewPadding;
// }
thumbPosition[0] = px;
postInvalidate();
}
private float checkIntPosition(float x) {
float total = measuredWidth / 2f - viewPadding;
float current = Math.abs(x - measuredWidth / 2f);
float percent = current / total;
boolean isLeft = x < measuredWidth / 2f;
if (isLeft) {
float flMin = percent * minValue;
BigDecimal bigDecimal = new BigDecimal(flMin);
bigDecimal = bigDecimal.setScale(1, RoundingMode.HALF_UP);
float px = bigDecimal.floatValue() / minValue * measuredWidth / 2f;
return measuredWidth / 2f - px;
} else {
float flMax = percent * maxValue;
BigDecimal bigDecimal = new BigDecimal(flMax);
bigDecimal = bigDecimal.setScale(1, RoundingMode.HALF_UP);
float px = bigDecimal.floatValue() / maxValue * (measuredWidth / 2f);
return px + measuredWidth / 2f;
}
}
public void setMaxValue(int maxValue) {
this.maxValue = maxValue;
}
public void setMinValue(int minValue) {
this.minValue = minValue;
}
public void setThumbRadius(int thumbRadius) {
this.thumbRadius = thumbRadius;
}
private boolean checkInThumb(float x, float y) {
return checkPosition(thumbPosition[0], thumbPosition[1], thumbRadius * 2, x, y);
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
private int dip2px(float dpValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
private int px2dip(float pxValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public void setEnable(boolean enable) {
setEnabled(enable);
}
/**
* 判断坐标是否在指定范围内
*
* @param targetX 目标x
* @param targetY 目标y
* @param size 尺寸
* @param x x
* @param y y
* @return
*/
private boolean checkPosition(float targetX, float targetY, float size, float x, float y) {
float distanceX = Math.abs(targetX + size / 2 - x);
float distanceY = Math.abs(targetY + size / 2 - y);
double distanceZ = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));
return distanceZ < size / 2;
}
/**
* 判断浮点类型数据是不是整数,整数去除小数点
*
* @param d double类型数据
* @return string数据
*/
public static String doubleTrans(float d) {
if (Math.round(d) - d == 0) {
return String.valueOf((long) d);
}
return String.valueOf(d);
}
网友评论