先上效果图:

先来啰嗦几句,哈哈哈

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

先说使用流程:

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

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

  1. android类中定义颜色,自定义实现简单的Android颜色选择器(附带源码)

    在写Android App过程中需要一个简单的颜色选择器,Android自带的ColorPicker和网上的一些ColorPicker都太高端了,都实现了颜色渐变功能,我要的不需要那么复杂,只想提供几 ...

  2. Android颜色选择器库

    2019独角兽企业重金招聘Python工程师标准>>> 如果您需要使用选择颜色的功能的话, 有2个比较好的颜色选择器开源库可以使用: 1.android-ColorPickerPre ...

  3. android自定义颜色选择器,自定义View:Android 仿 PS 选色板

    前言 今天突然发现年前的文章竟然没有写完,略微有点尴尬.今天分享的主题是Android仿PS选色板. 记得我刚开始学习Android的时候,就一直对PS选色板有一种执着,终于在今年找到了理想的解决方案 ...

  4. ESP32 开发笔记(四)LVGL控件学习 ColorPicker 颜色选择器控件

    先看效果,创建一个颜色选择器控件,设置事件回调动态显示当前选择的颜色值 开发板购买链接https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.5 ...

  5. Android 自定义View取色盘、颜色选择器、可根据颜色值反向定位坐标

    前言: 前段时间项目中需要用到色盘取色的功能,百度了许多相关的颜色选择器,发现这方面自定义View例子比较少,有用图片代替色盘的通过bitmap取色,但是只能取色,无法通过颜色值去定位在色盘上的坐标, ...

  6. Android 自定义View颜色选择器( 条形、水平),使用HSV颜色模型实现取色器并反向定位颜色所在位置

    轻松实现一个简单的Android条形水平颜色选择器,可以通过设置颜色值反向定位滑块 Demo地址:https://github.com/DonTiny/ColorPickDemo 效果图: 先贴完整代 ...

  7. Android上一种用于选择颜色的控件(颜色选择器)

    目录 引言 核心代码 控件整体代码 demo 引言 最近在做一个项目时其中有一个需求–自定义灯光颜色.要求通过手机端控制灯光颜色,手机端预设五种颜色及用户可自定义颜色.在百度上搜索找到一个开源的色环控 ...

  8. 《Android开发卷——自定义日期选择器(二)》

    (小米手机) (中兴手机) 在上一篇中,我介绍了一般公司都会自定义时间日期选择器,并结合自己所做的项目给大家参考. 工作实录之<Android开发卷--自定义日期选择器(一)>链接:htt ...

  9. android简单的颜色选择器制作

    前两天需要开发一个蓝牙通信控制灯的颜色的项目,上网找了一个关于颜色选择器制作的帖子. 众所周知,android的控件只完成了基本的功能,对于像颜色选择的功能则需要自定义控件的使用. 网上的帖子主要都是 ...

最新文章

  1. echarts词云图形状_怎么用Python画出好看的词云图?
  2. 腾讯云,物联网通信产品,动态注册步骤
  3. 并行编程——内存模型之缓存一致性
  4. [Leetcode][第120题][JAVA][三角形最小路径和][动态规划][递归]
  5. python struct pack解析_Python struct 详解
  6. SPOJ AMR12B 720
  7. config userc.php,框架内置Config.php配置
  8. 计算机安全防范系统维护,安防系统维护与设备维修(全彩)
  9. hystrix文档翻译之metrics
  10. 用户故事与敏捷方法笔记---Scrum与用户故事
  11. 微信推送封面尺寸_微信公众号封面图、正文配图尺寸如何?如何选择、制作?...
  12. 5W2H 分析法
  13. That's why you go away
  14. Android中framework层下添加aidl编译说程序包不存在
  15. 如何用Mathpix 和 MathType在WPS快速输入数学公式
  16. Python常见的魔方方法
  17. ROS1云课→28机器人代价地图配置
  18. MCU-CPU-GPU-APU系列
  19. R语言 | 利用tushare获取股票k线、市值、换手率,市盈率等指标
  20. Java API 访问HA模式下的HDFS集群

热门文章

  1. access2003安装包百度云_access2003数据库
  2. 高新技术企业上市要达到的条件
  3. PTA 7-43 快速求和(误差修正版)
  4. 11.5 Vue day06 父子组件通信、自定义事件
  5. Element Plus图标显示使用教程
  6. 《MySQL 入门教程》第 32 篇 存储过程(二)
  7. 服务端和客户端的cookie传递
  8. IOS-datepick
  9. Vue3官网-可复用组合式API(十四)实例 property(\$slots,\$attrs)、渲染函数render(虚拟节点VNode,h() 参数,使用JavaScript代替模板功能),插件
  10. UIWindow.h详解