Android 颜色选择器 自定义漂亮色环 提供事件回调

来源:互联网 发布:麦道夫骗局知乎 编辑:程序博客网 时间:2024/04/28 03:05

先上效果图:






先来啰嗦几句,哈哈哈

此控件真是一波三折啊,算了,还是直接说最终代码流程吧


先说使用流程:

1.XML配置

<com.zhuoapp.opple.view.ColorTouchView    android:id="@+id/color_view"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    />

2.UI绑定事件,是不是很简单

mColorView.setOnColorViewTouchListener(new OnColorViewTouchListener() {    @Override    public void onUpEvent(final int color) {      }    @Override    public void onMoveEvent(int color) {          }    @Override    public void onDownEvent(int color) {     }    @Override    public void onCancelEvent(int color) {     }});

3.整个类源码如下

public class ColorTouchView extends View {   // 画笔抗锯齿   public Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);// 渐变色环画笔   public Paint mPaintLoc = new Paint(Paint.ANTI_ALIAS_FLAG);//   public Paint mPaintFilter = new Paint(Paint.ANTI_ALIAS_FLAG);//   // 三十六个色相RGB值,存放默认HSL转化来的RGB值   // (H对应360度平分36份的点,S对应为饱和度[默认为0.5],L对应为亮度[默认为0.5])   public int[] mCircleColors = new int[36];   private int alpha = 255;   public Shader s;   private RadialGradient radialGradient;   public int num = 36;   public int[] colorArray = new int[num];   public int currColor = Color.argb(255, 235, 235, 235);   private int borderColor = Color.parseColor("#aeaeae");   private int pointColor = Color.parseColor("#ffffff");   // 取色圆的初始位置为颜色盘的最右侧   public int x_touchCircle;// 初始化取色圆的圆心的x坐标为宽度的90%   public int y_touchCircle;// 初始化取色圆的圆心的y坐标为高度的50%   // 小圆半径   public int r_touchCircle = dip2px(6);   public int touchAreaDis = dip2px(20);   public int height; // 屏幕高度   public int width;// 屏幕宽度   public int step = 0;// 绘制次数   public int Rmax;// 最大半径为宽度的40%   public int Rmin;// 最小半径为宽度的26.1955%(经过计算)   private static int x_circle, y_circle;   private RectF mRectF;   private long lastTouchUpTime, currTouchDownTime;   private Context mContext;   public ColorTouchView(Context context, AttributeSet attrs) {      super(context, attrs);      this.mContext = context;   }   protected void onDraw(Canvas canvas) {      super.onDraw(canvas);      if (x_touchCircle == 0)         x_touchCircle = (int) (width * 0.9);      if (y_touchCircle == 0)         y_touchCircle = (int) (height * 0.5);      calLocation();//        for (int j = 0; j < step; j++) {      int j = 0;      for (int w = 0; w < num - 1; w++) {         colorArray[w] = ColorUtil.HSL2RGB(new double[]{               360.0 / num * w, 1 - 0.6 / step * j, 1});      }      colorArray[num - 1] = colorArray[0];      for (int i = 0; i < num; i++) {         mCircleColors[i] = Color.argb(alpha, Color.red(colorArray[i]),               Color.green(colorArray[i]), Color.blue(colorArray[i]));      }      s = new SweepGradient(x_circle, y_circle, mCircleColors, null);      mPaint.setShader(s);      canvas.drawCircle(x_circle, y_circle, Rmax - step / 2, mPaint);      //画外部轮廓      canvas.drawCircle(x_circle,y_circle,Rmax+r_touchCircle/2,mPaintLoc);//        }      //画透明度      canvas.drawCircle(x_circle, y_circle, Rmax - step / 2, mPaintFilter);      mPaint.setColor(borderColor);      // 画外部轮廊      canvas.drawCircle(x_circle, y_circle, Rmax, mPaintLoc);      // 画内部轮廊      canvas.drawCircle(x_circle, y_circle, Rmin, mPaintLoc);//        canvas.drawBitmap(((BitmapDrawable) gd).getBitmap());      // 画圆点      mPaint.setColor(pointColor);      mPaintLoc.setStrokeWidth(dip2px(1));      if (!touchFlag) {         canvas.drawCircle(x_touchCircle, y_touchCircle, r_touchCircle,               mPaintLoc);      }   }   private boolean touchFlag = false;   @Override   public boolean onTouchEvent(MotionEvent event) {      // 圆心坐标      x_circle = (int) (width * 0.5);      y_circle = (int) (height * 0.5);      currTouchDownTime = System.currentTimeMillis();      // 两次调色时间需要大于400s      if (currTouchDownTime - lastTouchUpTime > 400) {         // 触摸点         int aimX = (int) event.getX();         int aimY = (int) event.getY();         double temp = (aimX - x_circle) * (aimX - x_circle)               + (aimY - y_circle) * (aimY - y_circle);         double currR = Math.sqrt(temp);//            int zone = (int) (currR - Rmin);         // 是否色环上         boolean isCir = currR  >= Rmin-touchAreaDis && currR <= Rmax +touchAreaDis;         switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:               if (isCir) {                  touchFlag = true;                  invalidate();                  currColor = ColorUtil.position2RGB(aimX, aimY, x_circle,                        y_circle, Rmax, Rmin);                  if (onColorViewTouchListener != null) {                     onColorViewTouchListener.onDownEvent(currColor);                  }               }            case MotionEvent.ACTION_MOVE:               if (isCir && touchFlag) {                  currColor = ColorUtil.position2RGB(aimX, aimY, x_circle,                        y_circle, Rmax, Rmin);                  if (onColorViewTouchListener != null) {                     onColorViewTouchListener.onMoveEvent(currColor);                  }               }               break;            case MotionEvent.ACTION_UP:               if (isCir && touchFlag) {                  currColor = ColorUtil.position2RGB(aimX, aimY, x_circle,                        y_circle, Rmax, Rmin);                  if (onColorViewTouchListener != null) {                     onColorViewTouchListener.onUpEvent(currColor);                  }               }               touchFlag = false;               setCurrColor(currColor);               lastTouchUpTime = System.currentTimeMillis();               break;            default:               break;         }      }      return true;   }   // 设置初始值   public void setCurrColor(int color) {      this.currColor = color;      invalidate();   }   /**    * 根据颜色计算位置    */   private void calLocation() {      double[] convertedHsl = ColorUtil.RGB2HSL(currColor);      double angle = convertedHsl[0];      double saturation = convertedHsl[1];      // 所在点距内环的距离      double distance = Rmax * saturation - Rmin;      distance = distance < 0 ? 0 : distance;      distance = distance > (Rmax - Rmin) ? (Rmax - Rmin) : distance;      double currColorR = Rmin + distance;      if (currColorR > Rmax) {         currColorR = Rmax;      }      double radians = Math.toRadians(angle);      x_touchCircle = (int) (currColorR * Math.cos(radians) + width * .5);      y_touchCircle = (int) (currColorR * Math.sin(radians) + height * .5);   }   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//    setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));      height = MeasureSpec.getSize(widthMeasureSpec);      width = height;      Rmax = (int) (width * 0.46);      Rmin = (int) (width * 0.46 * .36);      step = Rmax - Rmin;      int r = Rmax - step / 2;      mRectF = new RectF(x_circle - r, y_circle - r, x_circle + r,            y_circle + r);      x_circle = (int) (width * 0.5);      y_circle = (int) (height * 0.5);      mPaint.setStyle(Paint.Style.STROKE);      mPaint.setStrokeWidth(step);      mPaintLoc.setStyle(Paint.Style.STROKE);// 设置空心      mPaintLoc.setColor(borderColor);      mPaintLoc.setStrokeWidth(dip2px(1));      int sc = Color.parseColor("#e0FFFFFF");      int ec = Color.parseColor("#00ffffff");      int startAlpha = Color.alpha(sc);      int endAlpha = Color.alpha(ec);      int[] colors = new int[Rmax];      float[] pos = new float[Rmax];      for (int i = 0; i < Rmax; i++) {         if (i < Rmin) {            colors[i] = Color.TRANSPARENT;         } else {            pos[i] = (float) Math.sin((i - Rmin + 1) * 1.0f / step);            int a = startAlpha - (int) ((startAlpha - endAlpha) * pos[i]);            colors[i] = Color.argb(a, Color.red(sc), Color.green(sc), Color.blue(sc));         }         pos[i] = (i + 1) * 1.0f / Rmax;      }      radialGradient = new RadialGradient(x_circle, y_circle, Rmax, colors, pos, Shader.TileMode.REPEAT);      mPaintFilter.setShader(radialGradient);      mPaintFilter.setStyle(Paint.Style.STROKE);      mPaintFilter.setStrokeWidth(step);      mPaintFilter.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));      setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);   }    /*    android.graphics.PorterDuff.Mode.SRC:只绘制源图像    android.graphics.PorterDuff.Mode.DST:只绘制目标图像    android.graphics.PorterDuff.Mode.DST_OVER:在源图像的顶部绘制目标图像    android.graphics.PorterDuff.Mode.DST_IN:只在源图像和目标图像相交的地方绘制目标图像    android.graphics.PorterDuff.Mode.DST_OUT:只在源图像和目标图像不相交的地方绘制目标图像    android.graphics.PorterDuff.Mode.DST_ATOP:在源图像和目标图像相交的地方绘制目标图像,在不相交的地方绘制源图像    android.graphics.PorterDuff.Mode.SRC_OVER:在目标图像的顶部绘制源图像    android.graphics.PorterDuff.Mode.SRC_IN:只在源图像和目标图像相交的地方绘制源图像    android.graphics.PorterDuff.Mode.SRC_OUT:只在源图像和目标图像不相交的地方绘制源图像    android.graphics.PorterDuff.Mode.SRC_ATOP:在源图像和目标图像相交的地方绘制源图像,在不相交的地方绘制目标图像    android.graphics.PorterDuff.Mode.XOR:在源图像和目标图像重叠之外的任何地方绘制他们,而在不重叠的地方不绘制任何内容    android.graphics.PorterDuff.Mode.LIGHTEN:获得每个位置上两幅图像中最亮的像素并显示    android.graphics.PorterDuff.Mode.DARKEN:获得每个位置上两幅图像中最暗的像素并显示    android.graphics.PorterDuff.Mode.MULTIPLY:将每个位置的两个像素相乘,除以255,然后使用该值创建一个新的像素进行显示。结果颜色=顶部颜色*底部颜色/255    android.graphics.PorterDuff.Mode.SCREEN:反转每个颜色,执行相同的操作(将他们相乘并除以255),然后再次反转。结果颜色=255-(((255-顶部颜色)*(255-底部颜色))/255)     */   public boolean inOutCircle(float x, float y, float outRadius, float inRadius) {      double outCircle = outRadius;      double inCircle = inRadius;      double fingerCircle = Math.sqrt(x * x + y * y);      if (fingerCircle <= outCircle && fingerCircle >= inCircle) {         return true;      } else {         return false;      }   }   private OnColorViewTouchListener onColorViewTouchListener;   public void setOnColorViewTouchListener(         OnColorViewTouchListener onColorViewTouchListener) {      this.onColorViewTouchListener = onColorViewTouchListener;   }   public interface OnColorViewTouchListener {      public void onUpEvent(int color);      public void onDownEvent(int color);      public void onMoveEvent(int color);      public void onCancelEvent(int color);   }   private int dip2px(float dpValue) {      final float scale = getContext().getResources().getDisplayMetrics().density;      return (int) (dpValue * scale + 0.5f);   }}


原创粉丝点击