【移动应用开发技术】怎么在android中通过自定义View实现一个圆环颜色选择器_第1页
【移动应用开发技术】怎么在android中通过自定义View实现一个圆环颜色选择器_第2页
【移动应用开发技术】怎么在android中通过自定义View实现一个圆环颜色选择器_第3页
【移动应用开发技术】怎么在android中通过自定义View实现一个圆环颜色选择器_第4页
【移动应用开发技术】怎么在android中通过自定义View实现一个圆环颜色选择器_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么在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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论