Android 颜色选择器 自定义漂亮色环 提供事件回调 - Go语言中文社区

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


先上效果图:






先来啰嗦几句,哈哈哈

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


先说使用流程:

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);
   }


}


版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_39976195/article/details/77680364
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 22:15:14
  • 阅读 ( 1173 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢