public class ColorSelectBar extends View {
//控件的高度
private int mBarHeight;
//控件的宽度
private int mBarWidth;
//定义画笔
private Paint paint;
//圆圈的半径
private int mBarPointerRadius;
private RectF mBarRect = new RectF();
//圆圈的圆心坐标
private int cX, cY;
//定义线性渲染
private LinearGradient linearGradient;
//画圆的画笔
private Paint circlePaint;
//渐变的颜色集合
private static final int[] COLORS = new int[]{0xFF000000, 0xFF808080, 0xFFFFFFFF, 0xFFFF0000, 0xFFFF00FF,
0xFF0000FF, 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000};
//选择的颜色
private int selectColor = Color.parseColor("#ff000000");
//记录是否可以移动
private boolean mIsMovingPointer;
//颜色变化的监听器
ColorChangeListener colorChangeListener;
public ColorSelectBar(Context context) {
super(context);
init(null, 0);
}
public ColorSelectBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public ColorSelectBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
}
private void init(AttributeSet attrs, int defStyle) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ColorSelectBar, defStyle, 0);
final Resources resources = getContext().getResources();
//获取高度
mBarHeight = a.getDimensionPixelSize(R.styleable.ColorSelectBar_bar_height, resources.getDimensionPixelSize(R.dimen.bar_height));
//获取宽度
mBarWidth = a.getDimensionPixelSize(R.styleable.ColorSelectBar_bar_width, resources.getDimensionPixelSize(R.dimen.bar_width));
//获取半径
mBarPointerRadius = a.getDimensionPixelSize(R.styleable.ColorSelectBar_pointer_radius, resources.getDimensionPixelSize(R.dimen.bar_pointer_radius));
a.recycle();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
//定义画圆的画笔
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取mode和size
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
//根据mode来确定size
if (widthMode == MeasureSpec.EXACTLY) {
mBarWidth = widthSize - mBarPointerRadius * 2;
} else if (widthMode == MeasureSpec.AT_MOST) {
mBarWidth = Math.min(mBarWidth, widthSize);
}
//确定高度
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
mBarHeight = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
mBarHeight = Math.min(mBarHeight, heightSize);
}
//确定最终大小布局
setMeasuredDimension(widthSize, mBarPointerRadius * 2);
//确定矩形的位置
mBarRect.set(mBarPointerRadius,
mBarPointerRadius - (mBarHeight / 2),
mBarWidth + mBarPointerRadius,
(mBarPointerRadius + (mBarHeight / 2))
);
//计算圆心的位置
cX = mBarWidth + mBarPointerRadius;
cY = mBarPointerRadius;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (null == linearGradient) {
linearGradient = new LinearGradient(mBarPointerRadius, 0, mBarWidth + mBarPointerRadius, mBarHeight, COLORS, null, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
}
canvas.drawRect(mBarRect, paint); //绘制矩形
circlePaint.setColor(selectColor);
canvas.drawCircle(cX, cY, mBarPointerRadius, circlePaint); //绘制圆圈
}
@Override
public boolean onTouchEvent(MotionEvent event) {
getParent().requestDisallowInterceptTouchEvent(true);
int action = event.getAction();
//只是水平的滑动,故只记录x值的变化
float dimen;
dimen = event.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (dimen >= mBarPointerRadius && dimen <= mBarPointerRadius + mBarWidth) {
mIsMovingPointer = true;
drawAgain(dimen);
}
break;
case MotionEvent.ACTION_MOVE:
if (mIsMovingPointer) {
if (dimen >= mBarPointerRadius
&& dimen <= (mBarPointerRadius + mBarWidth)) {
drawAgain(dimen);
}
}
break;
case MotionEvent.ACTION_UP:
mIsMovingPointer = false;
break;
}
return true;
}
private int ave(int s, int d, float p) {
return s + Math.round(p * (d - s));
}
//根据位置来计算相应的颜色值
private int calculateColor(float x) {
float unit = x / (mBarPointerRadius + mBarWidth);
if (unit < 0) {
unit += 1;
}
if (unit <= 0) {
return COLORS[0];
}
if (unit >= 1) {
return COLORS[COLORS.length - 1];
}
float p = unit * (COLORS.length - 1);
int i = (int) p;
p -= i;
int c0 = COLORS[i];
int c1 = COLORS[i + 1];
int a = ave(Color.alpha(c0), Color.alpha(c1), p);
int r = ave(Color.red(c0), Color.red(c1), p);
int g = ave(Color.green(c0), Color.green(c1), p);
int b = ave(Color.blue(c0), Color.blue(c1), p);
return Color.argb(a, r, g, b);
}
//定义个接口,颜色发生变化的接口监听
public interface ColorChangeListener {
public void onColorChanged(int value);
}
public void setColorChangeListener(ColorChangeListener colorChangeListener) {
this.colorChangeListener = colorChangeListener;
}
/**
* 重新绘制
*/
private void drawAgain(float dimen) {
cX = Math.round(dimen);
selectColor = calculateColor(cX);
invalidate();
if (null != colorChangeListener)
colorChangeListener.onColorChanged(selectColor);
}
}
实现效果类似于:
ps:需要在dimens文件中自定义,颜色条的宽、高和拖动圆形的半径。在attr文件中定义,自定义颜色条的属性,及属性参数。
如:
<declare-styleable name="ColorSelectBar">
<!--高度-->
<attr name="bar_height" format="dimension"></attr>
<!--宽度-->
<attr name="bar_width" format="dimension"></attr>
<!--圆圈的半径-->
<attr name="pointer_radius" format="dimension"></attr>
</declare-styleable>