版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么在android中通过自定义View实现一个圆环颜色选择器
这篇文章给大家介绍怎么在android中通过自定义View实现一个圆环颜色选择器,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。public
class
MyColorPicker
extends
View
{
private
int
mThumbHeight;
private
int
mThumbWidth;
private
String[]
colors
;
private
int
sections;
//每个小块的度数
private
int
sectionAngle;
private
Paint
mPaint;
private
int
ringWidth;
private
RectF
mRectF;
private
Drawable
mThumbDrawable
=
null;
private
float
mThumbLeft;
private
float
mThumbTop;
private
double
mViewCenterX,
mViewCenterY;
private
double
mViewRadisu;
//起始角度
private
int
mStartDegree
=
-90;
//当前view的尺寸
private
int
mViewSize;
private
int
textColor;
private
String
text="";
private
Paint
textPaint;
private
Rect
mBounds;
private
float
textSize;
private
int
colorType;
private
int
default_size
=
100;
public
MyColorPicker(Context
context)
{
this(context,
null);
}
public
MyColorPicker(Context
context,
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
MyColorPicker(Context
context,
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
TypedArray
localTypedArray
=
context.obtainStyledAttributes(attrs,
R.styleable.CircleColorPicker);
mThumbDrawable
=
localTypedArray.getDrawable(R.styleable.CircleColorPicker_thumb);
ringWidth
=
(int)
localTypedArray.getDimension(R.styleable.CircleColorPicker_ring_span,
30);
colorType
=
localTypedArray.getInt(R.styleable.CircleColorPicker_color_type,
0);
textColor
=
localTypedArray.getColor(R.styleable.CircleColorPicker_text_color,
Color.BLACK);
text
=
localTypedArray.getString(R.styleable.CircleColorPicker_text);
textSize
=
localTypedArray.getDimension(R.styleable.CircleColorPicker_text_size,
20);
localTypedArray.recycle();
default_size
=
SystemUtils.dip2px(context,
260);
init();
}
private
void
init()
{
colors
=
colorType
==
1
?
ColorUtils.getMacaroon():ColorUtils.getAllColors();
sections
=
colors.length;
mPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(ringWidth);
textPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
mThumbWidth
=
this.mThumbDrawable.getIntrinsicWidth();
mThumbHeight
=
this.mThumbDrawable.getIntrinsicHeight();
sectionAngle
=
360/sections;
mBounds
=
new
Rect();
}
@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
//
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
setMeasuredDimension(getMeasuredLength(widthMeasureSpec,
true),
getMeasuredLength(heightMeasureSpec,
false));
int
circleX
=
getMeasuredWidth();
int
circleY
=
getMeasuredHeight();
if
(circleY
<
circleX)
{
circleX
=
circleY;
}
mViewSize
=
circleX;
mViewCenterX
=
circleX/2;
mViewCenterY
=
circleY/2;
mViewRadisu
=
circleX/2
-
mThumbWidth
/
2;
setThumbPosition(Math.toRadians(mStartDegree));
}
private
int
getMeasuredLength(int
length,
boolean
isWidth)
{
int
specMode
=
MeasureSpec.getMode(length);
int
specSize
=
MeasureSpec.getSize(length);
int
size;
int
padding
=
isWidth
?
getPaddingLeft()
+
getPaddingRight()
:
getPaddingTop()
+
getPaddingBottom();
if
(specMode
==
MeasureSpec.EXACTLY)
{
size
=
specSize;
}
else
{
size
=
default_size
+
padding;
if
(specMode
==
MeasureSpec.AT_MOST)
{
size
=
Math.min(size,
specSize);
}
}
return
size;
}
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
mRectF
=
new
RectF(0+mThumbWidth/2,
0+mThumbWidth/2,
mViewSize-mThumbWidth/2,
mViewSize-mThumbWidth/2);
for
(int
i
=
0;
i
<
colors.length;
i++)
{
mPaint.setColor(Color.parseColor(colors[i]));
canvas.drawArc(mRectF,
i*sectionAngle-90,
sectionAngle+1,false,
mPaint);
}
mThumbDrawable.setBounds((int)
mThumbLeft,
(int)
mThumbTop,
(int)
(mThumbLeft
+
mThumbWidth),
(int)
(mThumbTop
+
mThumbHeight));
mThumbDrawable.draw(canvas);
textPaint.getTextBounds(text,
0,
text.length(),
mBounds);
float
textWidth
=
mBounds.width();
float
textHeight
=
mBounds.height();
float
textLeft
=
(float)
(mViewCenterX
-
textWidth/2);
float
textTop
=
(float)(mViewCenterY
+
textHeight/2);
canvas.drawText(text,
0,
text.length(),
textLeft,
textTop,
textPaint);
}
private
void
setThumbPosition(double
radian)
{
double
x
=
mViewCenterX
+
mViewRadisu
*
Math.cos(radian);
double
y
=
mViewCenterY
+
mViewRadisu
*
Math.sin(radian);
mThumbLeft
=
(float)
(x
-
mThumbWidth
/
2);
mThumbTop
=
(float)
(y
-
mThumbHeight
/
2);
}
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
float
eventX
=
event.getX();
float
eventY
=
event.getY();
switch
(event.getAction())
{
case
MotionEvent.ACTION_DOWN:
seekTo(eventX,
eventY,
false);
break
;
case
MotionEvent.ACTION_MOVE:
seekTo(eventX,
eventY,
false);
break
;
case
MotionEvent.ACTION_UP:
//
seekTo(eventX,
eventY,
true);
float
part
=
sectionAngle
/
4.0f;
for
(int
i
=
0;
i
<
sections;
i++)
{
if
(
mSweepDegree
>
(i-1)*sectionAngle+part*3
&&
mSweepDegree
<
i
*sectionAngle
+
part)
{
if
(mSweepDegree
<
i*sectionAngle)
{
setThumbPosition(Math.toRadians((i-1)*sectionAngle+part*2));
}else
{
setThumbPosition(Math.toRadians(i*sectionAngle+part*2));
}
}
}
if
(mSweepDegree
>
((sections-1)*sectionAngle)+part*3)
{
setThumbPosition(Math.toRadians((sections-1)*sectionAngle+part*2));
}
invalidate();
break
;
}
return
true;
}
private
int
preColor;
private
float
mSweepDegree;
private
void
seekTo(float
eventX,
float
eventY,
boolean
isUp)
{
if
(true
==
isPointOnThumb(eventX,
eventY)
&&
false
==
isUp)
{
//
mThumbDrawable.setState(mThumbPressed);
double
radian
=
Math.atan2(eventY
-
mViewCenterY,
eventX
-
mViewCenterX);
/*
*
由于atan2返回的值为[-pi,pi]
*
因此需要将弧度值转换一下,使得区间为[0,2*pi]
*/
if
(radian
<
0){
radian
=
radian
+
2*Math.PI;
}
setThumbPosition(radian);
mSweepDegree
=
(float)
Math.round(Math.toDegrees(radian));
int
currentColor
=
getColor(mSweepDegree);
if
(currentColor
!=
preColor)
{
preColor
=
currentColor;
if
(onColorChangeListener
!=
null)
{
onColorChangeListener.colorChange(preColor);
}
}
invalidate();
}else{
//
mThumbDrawable.setState(mThumbNormal);
invalidate();
}
}
private
int
getColor(float
mSweepDegree)
{
int
tempIndex
=
(int)
(mSweepDegree/sectionAngle);
int
num
=
90
/
sectionAngle;
if
(tempIndex
==sections)
{
tempIndex
=
0;
}
int
index
=
tempIndex;
if
(tempIndex
>=
0)
{
index
=
tempIndex+num;
}
if
(tempIndex
>=
(sections-num))
{
index
=
tempIndex-(sections-num);
}
return
Color.parseColor(colors[index]);
}
private
boolean
isPointOnThumb(float
eventX,
float
eventY)
{
boolean
result
=
false;
double
distance
=
Math.sqrt(Math.pow(eventX
-
mViewCenterX,
2)
+
Math.pow(eventY
-
mViewCenterY,
2));
if
(distance
<
mViewSize
&&
distance
>
(mViewSize
/
2
-
mThumbWidth)){
result
=
true;
}
return
result;
}
public
int
getCurrentColor()
{
return
preColor;
}
public
void
setStartColor(String
color)
{
for
(int
i
=
0;
i
<
colors.length;
i++)
{
if
(colors[i].equals(color))
{
preColor
=
Color.parseColor(colors[i]);
int
sweepAngle
=
(i-
90
/sectionAngle)*sectionAngle+sectionAngle/2;
//
postDelayed(()->{
//
setThumbPosition(Math.toRadians(sweepAngle));
//
invalidate();
//
},200);
mStartDegree
=
sweepAngle;
//最好加上
invalidate();
break;
}
}
}
public
void
setColor(String
color)
{
for
(int
i
=
0;
i
<
colors.length;
i++)
{
if
(colors[i].equals(color))
{
preColor
=
Color.parseColor(colors[i]);
int
sweepAngle
=
(i-
90
/sectionAngle)*sectionAngle+sectionAngle/2;
setThumbPosition(Math.toRadians(sweepAngle));
invalidate();
break;
}
}
}
public
interface
OnColorChangeListener
{
void
colorChange(int
color);
}
public
void
setOnColorChangeListener(OnColorChangeListener
onColorChangeListener)
{
this.onColorChangeListener
=
onColorChangeListener;
}
private
OnColorChangeListener
onColorChangeListener;
}注意的几个地方:1.可滑动位置的判断以及如何求滑动的角度,这里还去脑补了下atan2这个三角函数2.设置指示器的开始的位置,外部调用setStartColor()方法时,这个View可能还没真正完成绘制。如果没有完成绘制,第几行的invalidate()方法其实是没多大作用。上面是选择单个颜色,下面来个加强版,选择的是颜色区间,先上效果图:区间可以自己选择,并且可以反转(低指示器在高指示器顺时针方向或逆时针方向)。下面是代码:public
class
IntervalColorPicker
extends
View
{
private
int
mThumbHeight;
private
int
mThumbWidth;
private
int
mThumbLowHeight,
mThumbLowWidth;
private
String[]
colors
=
ColorUtils.getAllColors();
private
int
sections;
//每个小块的度数
private
int
sectionAngle;
private
Paint
mPaint;
private
Paint
arcPaint;
private
int
ringWidth;
private
RectF
mRectF;
private
Drawable
mThumbHighDrawable
=
null;
private
Drawable
mThumbLowDrawable;
private
float
mThumbLeft;
private
float
mThumbTop;
private
float
mThumbLowLeft,
mThumbLowTop;
private
double
mViewCenterX,
mViewCenterY;
private
double
mViewRadisu;
//起始角度
private
float
mStartDegree
=
270;
//当前view的尺寸
private
int
mViewSize;
//区间
private
int
interval
=
7;
private
boolean
reverse;
private
float
tempStartAngle
=
mStartDegree;
public
IntervalColorPicker(Context
context)
{
this(context,
null);
}
public
IntervalColorPicker(Context
context,
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
IntervalColorPicker(Context
context,
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
TypedArray
localTypedArray
=
context.obtainStyledAttributes(attrs,
R.styleable.IntervalColorPicker);
mThumbHighDrawable
=
localTypedArray.getDrawable(R.styleable.IntervalColorPicker_thumbHigh);
mThumbLowDrawable
=
localTypedArray.getDrawable(R.styleable.IntervalColorPicker_thumbLow);
ringWidth
=
(int)
localTypedArray.getDimension(R.styleable.IntervalColorPicker_ring_breadth,
30);
localTypedArray.recycle();
init();
}
private
void
init()
{
sections
=
colors.length;
mPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(ringWidth);
arcPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG);
arcPaint.setStyle(Paint.Style.STROKE);
arcPaint.setStrokeWidth(ringWidth
+
1);
arcPaint.setColor(Color.GRAY);
mThumbWidth
=
this.mThumbHighDrawable.getIntrinsicWidth();
mThumbHeight
=
this.mThumbHighDrawable.getIntrinsicHeight();
mThumbLowHeight
=
mThumbLowDrawable.getIntrinsicHeight();
mThumbLowWidth
=
mThumbHighDrawable.getIntrinsicWidth();
sectionAngle
=
360
/
sections;
}
@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
int
circleX
=
getMeasuredWidth();
int
circleY
=
getMeasuredHeight();
if
(circleY
<
circleX)
{
circleX
=
circleY;
}
mViewSize
=
circleX;
mViewCenterX
=
circleX
/
2;
mViewCenterY
=
circleY
/
2;
mViewRadisu
=
circleX
/
2
-
mThumbWidth
/
2;
}
private
float
sweepAngle;
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
mRectF
=
new
RectF(0
+
mThumbWidth
/
2,
0
+
mThumbWidth
/
2,
mViewSize
-
mThumbWidth
/
2,
mViewSize
-
mThumbWidth
/
2);
for
(int
i
=
0;
i
<
colors.length;
i++)
{
mPaint.setColor(Color.parseColor(colors[i]));
canvas.drawArc(mRectF,
i
*
sectionAngle
-
90,
sectionAngle
+
1,
false,
mPaint);
}
int
tempAng
=
(int)
(tempStartAngle
+
sweepAngle);
int
intervalAngle
=
interval
*
sectionAngle;
if
(reverse)
{
setThumbPosition(Math.toRadians(tempAng));
setThumbLowPosition(Math.toRadians(tempAng
-
intervalAngle));
canvas.drawArc(mRectF,
tempAng,
360
-
intervalAngle,
false,
arcPaint);
}
else
{
setThumbPosition(Math.toRadians(tempAng));
setThumbLowPosition(Math.toRadians(tempAng
+
intervalAngle));
canvas.drawArc(mRectF,
(int)
(tempAng
+
intervalAngle),
360
-
intervalAngle,
false,
arcPaint);
}
mThumbHighDrawable.setBounds((int)
mThumbLeft,
(int)
mThumbTop,
(int)
(mThumbLeft
+
mThumbWidth),
(int)
(mThumbTop
+
mThumbHeight));
mThumbLowDrawable.setBounds((int)
mThumbLowLeft,
(int)
mThumbLowTop,
(int)
(mThumbLowLeft
+
mThumbLowWidth),
(int)
(mThumbLowTop
+
mThumbLowHeight));
mThumbHighDrawable.draw(canvas);
mThumbLowDrawable.draw(canvas);
}
private
void
setThumbPosition(double
radian)
{
double
x
=
mViewCenterX
+
mViewRadisu
*
Math.cos(radian);
double
y
=
mViewCenterY
+
mViewRadisu
*
Math.sin(radian);
mThumbLeft
=
(float)
(x
-
mThumbWidth
/
2);
mThumbTop
=
(float)
(y
-
mThumbHeight
/
2);
}
private
void
setThumbLowPosition(double
radian)
{
double
x
=
mViewCenterX
+
mViewRadisu
*
Math.cos(radian);
double
y
=
mViewCenterY
+
mViewRadisu
*
Math.sin(radian);
mThumbLowLeft
=
(float)
(x
-
mThumbLowWidth
/
2);
mThumbLowTop
=
(float)
(y
-
mThumbLowHeight
/
2);
}
private
boolean
isDown
=
true;
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
float
eventX
=
event.getX();
float
eventY
=
event.getY();
switch
(event.getAction())
{
case
MotionEvent.ACTION_DOWN:
getEventDegree(eventX,
eventY);
//
seekTo(eventX,
eventY,
false);
break;
case
MotionEvent.ACTION_MOVE:
seekTo(eventX,
eventY);
break;
case
MotionEvent.ACTION_UP:
postDelayed(()
->
{
tempStartAngle
=
tempStartAngle
+
sweepAngle;
sweepAngle
=
0;
getSelectedColor();
if
(onColorChangeListener
!=
null)
{
onColorChangeListener.colorChange(selectedColors);
}
},
100);
break;
}
return
true;
}
private
float
downDegree;
private
void
getEventDegree(float
eventX,
float
eventY)
{
if
(isPointOnThumb(eventX,
eventY))
{
double
radian
=
Math.atan2(eventY
-
mViewCenterY,
eventX
-
mViewCenterX);
/*
*
由于atan2返回的值为[-pi,pi]
*
因此需要将弧度值转换一下,使得区间为[0,2*pi]
*/
if
(radian
<
0)
{
radian
=
radian
+
2
*
Math.PI;
}
isDown
=
true;
downDegree
=
Math.round(Math.toDegrees(radian));
}
else
{
isDown
=
false;
}
}
private
void
seekTo(float
eventX,
float
eventY)
{
if
(true
==
isPointOnThumb(eventX,
eventY))
{
//
mThumbHighDrawable.setState(mThumbPressed);
if
(!isDown)
{
getEventDegree(eventX,
eventY);
isDown
=
true;
}
double
radian
=
Math.atan2(eventY
-
mViewCenterY,
eventX
-
mViewCenterX);
/*
*
由于atan2返回的值为[-pi,pi]
*
因此需要将弧度值转换一下,使得区间为[0,2*pi]
*/
if
(radian
<
0)
{
radian
=
radian
+
2
*
Math.PI;
}
setThumbPosition(radian);
float
mSweepDegree
=
(float)
Math.round(Math.toDegrees(radian));
sweepAngle
=
mSweepDegree
-
downDegree;
invalidate();
}
}
//选中的颜色
private
ArrayList<Integer>
selectedColors
=
new
ArrayList<>(interval);
public
void
getSelectedColor()
{
int
tempIndex
=
(int)
(tempStartAngle
/
sectionAngle);
int
num
=
90
/
sectionAngle;
if
(tempIndex
==
sections)
{
tempIndex
=
0;
}
int
index
=
tempIndex;
if
(tempIndex
>=
0)
{
index
=
tempIndex
+
num;
}
if
(tempIndex
>=
(sections
-
num))
{
index
=
tempIndex
-
(sections
-
num);
}
if
(index>colors.length)
index
=
index%colors.length;
while
(index<0)
{
index
=
colors.length+index;
}
selectedColors.clear();
int
startIndex
=
0;
if
(reverse)
{
startIndex
=
index
-
interval
-1;
while
(startIndex
<
0)
{
startIndex
=
startIndex+colors.length;
}
if
(startIndex
>
index)
{
for
(int
i
=
startIndex+1;
i
<
colors.length;
i++)
{
selectedColors.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024-2030年数字全息术行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2024-2030年改性火木行业市场现状供需分析及市场深度研究发展前景及规划投资研究报告
- 2024-2030年换档套筒行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2024-2030年拳击游戏机行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2024-2030年护理中心行业市场发展分析及发展趋势与投资前景研究报告
- 2024-2030年托盘包装机行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2024-2030年手术针行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 2024-2030年手动气囊导管泵行业市场现状供需分析及市场深度研究发展前景及规划投资研究报告
- 2024-2030年房产交易管理行业市场发展现状及竞争格局与投资价值研究报告
- 2024-2030年成品油运输行业市场发展分析及前景趋势与投资研究报告
- 网络带宽管理策略
- 关于新形势下的育人方式变革与教学模式改进研修总结
- 肝胆外科常见疾病门静脉癌栓护理
- 米.伊林《十万个为什么》阅读题
- 瓷贴面修复技术教学课件
- 洗衣技术方案投标模板
- 深圳中考自主招生简历
- 2012东风本田cr v全车电路图
- 智能机床发展现状与技术体系框架
- 行星滚柱丝杠副-设计计算
- 第五章-小组工作后期
评论
0/150
提交评论