国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

android自定義View實現圓環顏色選擇器

2019-10-22 18:10:17
字體:
來源:轉載
供稿:網友

最近工作需要,自定了一個顏色選擇器,效果圖如下:

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()方法其實是沒多大作用。

上面是選擇單個顏色,下面來個加強版,選擇的是顏色區間,先上效果圖:

android,View,顏色選擇器

區間可以自己選擇,并且可以反轉(低指示器在高指示器順時針方向或逆時針方向)。

下面是代碼:

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.add(Color.parseColor(colors[i]));    }    for (int i = 0; i <= index; i++) {     selectedColors.add(Color.parseColor(colors[i]));    }   }else {    for (int i = startIndex+1; i <= index; i++) {     selectedColors.add(Color.parseColor(colors[i]));    }   }  }else {   startIndex = index+interval+1;   while (startIndex>colors.length)   {    startIndex = startIndex-colors.length;   }   if (startIndex < index)   {    for (int i = startIndex-1; i >= 0; i--) {     selectedColors.add(Color.parseColor(colors[i]));    }    for (int i = colors.length-1; i >= index; i--) {     selectedColors.add(Color.parseColor(colors[i]));    }   }else {    for (int i = startIndex-1; i >=index; i--) {     selectedColors.add(Color.parseColor(colors[i]));    }   }  } } 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 boolean isReverse() {  return reverse; } public void setReverse(boolean reverse) {  this.reverse = reverse;  invalidate(); } public interface OnColorChangeListener {  void colorChange(ArrayList<Integer> colors); } public void setOnColorChangeListener(OnColorChangeListener onColorChangeListener) {  this.onColorChangeListener = onColorChangeListener; } private OnColorChangeListener onColorChangeListener;}

注意的地方:

1. 手勢抬起時用了一個postDelayed方法,還是避免繪制的先后問題。 
2. isDown變量的作用是判斷,手勢按下時是否在圓環上。當手勢從圓環外滑倒圓環上時,避免指示器一下彈到手指位置。

github地址:colorpicker

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 浦城县| 曲麻莱县| 黄骅市| 确山县| 河西区| 车险| 安丘市| 台中县| 长沙市| 莱州市| 呼图壁县| 东山县| 广昌县| 青田县| 睢宁县| 双江| 漾濞| 德阳市| 革吉县| 荥经县| 会昌县| 大名县| 淮北市| 通河县| 垫江县| 潞城市| 鹰潭市| 建阳市| 郎溪县| 名山县| 赫章县| 荔波县| 韶山市| 大悟县| 伊金霍洛旗| 泰和县| 凤山县| 英吉沙县| 尉氏县| 中江县| 乐山市|