android开发分享Android圆环颜色选择器

一个非常不错的颜色圆环选择器视图,由于项目需要自己写了一个圆环颜色选择器,部分代码来源与网络,如有相同敬请谅解。废话不多说,直接上源代码:1、在values下创建一个attr.xml文件,用于定义视图的xml属性:<?xml version=”1.0″ encoding=”utf-8″?><resources> <declare-styleable name=”RingColorPicker”> <!–默认角度–>

一个非常不错的颜色圆环选择器视图,由于项目需要自己写了一个圆环颜色选择器,部分代码来源与网络,如有相同敬请谅解。废话不多说,直接上源代码:
1、在values下创建一个attr.xml文件,用于定义视图的xml属性:

<?xml version="1.0" encoding="utf-8"?> <resources>     <declare-styleable name="RingColorPicker">         <!--默认角度-->         <attr name="angle" format="float"/>         <!--圆形选择器填充色-->         <attr name="markBackground" format="color|reference"/>         <!--圆形选择器边框颜色-->         <attr name="markStrokeColor" format="color|reference"/>         <!--圆形选择器描边-->         <attr name="isMarkStroke" format="boolean"/>         <!--圆环宽度-->         <attr name="ringWidth" format="dimension"/>         <!--选择器自动色-->         <attr name="isMarkAutoColor" format="boolean"/>         <!--扩散特效透明度-->         <attr name="spreadAlpha" format="integer"/>         <!--选择器描边宽度-->         <attr name="markStrokeWidth" format="dimension|reference"/>         <!--中心按钮图像资源-->         <attr name="srcCompat" />         <!--中心按钮图像透明度-->         <attr name="centerImageAlpha" format="integer"/>         <!--中心复选状态-->         <attr name="checked" format="boolean"/>         <!--当前指向的颜色-->         <attr name="currentColor" format="color|reference"/>         <!--过滤颜色-->         <attr name="tint" />         <!--视图样式-->         <attr name="colorPickerStyle" format="enum">             <enum name="MARK_RING_INNER" value="0"/>             <enum name="MARK_RING_OUTER" value="1"/>             <enum name="MARK_RING_DOWN_OUTER" value="2"/>         </attr>     </declare-styleable> </resources> 

2、这里面使用到了一个自定义颜色工具类来替换Color类,在Color类的基础上增加了部分转换,代码如下:

import android.graphics.Color; import androidx.annotation.ColorInt; import androidx.annotation.ColorLong; import androidx.annotation.IntRange; import androidx.annotation.Size;  /**  * 颜色工具  */ public class ColorUnit extends Color {     public ColorUnit(){         super();     }     /**      * 将RGB组件转换为HSV。      * <ul>      * <li>hsv[0]是色调([0..360[)</li>      * <li>hsv[1]已饱和([0…1])</li>      * <li>hsv[2]是值([0…1])</li>      * </ul>      * @param red 红色分量值([0..255])      * @param green 绿色分量值([0..255])      * @param blue 蓝色分量值([0..255])      * @param hsv 3元素数组,用于保存生成的HSV组件。      */     public static void RGBToHSV(int red,int green, int blue,@Size(3) float hsv[]){         Color.RGBToHSV(red,green,blue,hsv);     }     /**      * 将RGB组件转换为HSV。      * <ul>      * <li>hsv[0]是色调([0..360[)</li>      * <li>hsv[1]已饱和([0…1])</li>      * <li>hsv[2]是值([0…1])</li>      * </ul>      * @param red 红色的分量([0..1])      * @param green 绿色的分量([0..1])      * @param blue 蓝色的分量([0..1])      * @param hsv 3元素数组,用于保存生成的HSV组件。      */     public static void RGBToHSV(float red, float green, float blue, @Size(3) float hsv[]){         if(red<0) {             red = 0;         }else if(red>1){             red = 1;         }         if(green<0) {             green = 0;         }else if(green>1){             green = 1;         }         if(blue<0) {             blue = 0;         }else if(blue>1){             blue = 1;         }         Color.RGBToHSV((int)(red*255.0f),(int)(green*255.0f),(int)(blue*255.0f),hsv);     }      /**      * 将HSV组件转为RGB组件      * @param hsv 3元素数组。      * <ul>      * <li>hsv[0]是色调([0..360[)</li>      * <li>hsv[1]色饱和([0…1])</li>      * <li>hsv[2]是值([0…1])</li>      * </ul>      * @param rgb 3元素数组,用于保存生成的HSV组件。      * <ul>      * <li>rgb[0]颜色的红色分量([0..1])</li>      * <li>rgb[1] 颜色的绿色分量([0..1])</li>      * <li>rgb[2] 颜色的蓝色量([0..1])</li>      * </ul>      */     public static void HSVToRGB(float hsv[], @Size(3) float rgb[]){         int color=Color.HSVToColor(hsv);         rgb[0]=Color.red(color);         rgb[1]=Color.green(color);         rgb[2]=Color.blue(color);       //  Color.colorToHSV();     }     /**      * 将HSV组件转为RGB组件      * @param hue 是色调([0..360[)      * @param saturation 色饱和([0…1])      * @param value 亮度值([0…1])      * @param rgb 3元素数组,用于保存生成的HSV组件。      *      <ul>      *      <li>rgb[0]颜色的红色分量([0..1])</li>      *      <li>rgb[1] 颜色的绿色分量([0..1])</li>      *      <li>rgb[2] 颜色的蓝色量([0..1])</li>      *      </ul>      */     public static void HSVToRGB(float hue,float saturation,float value, @Size(3) float rgb[]){         float hsv[]={hue,saturation,value};         HSVToRGB(hsv,rgb);     }      /**      * 将HSV组件转换为ARGB颜色。Alpha设置为0xFF。      * @param hue 色调([0..360[)      * @param saturation 色饱和([0…1])      * @param value 亮度值([0…1])      * @return Argb颜色      */     public static int HSVToColor(float hue,float saturation,float value){         float hsv[]={hue,saturation,value};         return   Color.HSVToColor(hsv);     }      /**      * 将HSV组件转换为ARGB颜色。alpha分量通过不变。      * @param alpha 返回的argb颜色的alpha分量。      * @param hue 色调([0..360[)      * @param saturation 色饱和([0…1])      * @param value 亮度值([0…1])      * @return Argb颜色      */     public static int HSVToColor(@IntRange(from = 0, to = 255) int alpha,float hue,float saturation,float value){         float hsv[]={hue,saturation,value};         return   Color.HSVToColor(alpha,hsv);     }     /**      * 从范围([0..1])内的alpha、red、green、blue float组件返回一个颜色int。如果组件超出范围,则返回的颜色未定义。      * @param alpha 颜色的Alpha分量([0..1])      * @param red 颜色的红色分量([0..1])      * @param green 颜色的绿色分量([0..1])      * @param blue 颜色的蓝色量([0..1])      * @return      */     @ColorInt     public static int argb(float alpha, float red, float green, float blue){         if(alpha<0) {             alpha = 0;         }else if(alpha>1){             alpha = 1;         }         if(red<0) {             red = 0;         }else if(red>1){             red = 1;         }         if(green<0) {             green = 0;         }else if(green>1){             green = 1;         }         if(blue<0) {             blue = 0;         }else if(blue>1){             blue = 1;         }         return ((int) (alpha * 255.0f + 0.5f) << 24) |                 ((int) (red   * 255.0f + 0.5f) << 16) |                 ((int) (green * 255.0f + 0.5f) <<  8) |                 (int) (blue  * 255.0f + 0.5f);     }     /**      * 从范围([0..1])内的红色、绿色、蓝色浮点组件返回一个颜色int。alpha组件隐式地为1.0(完全不透明)。如果组件超出范围,则返回的颜色未定义。      * @param red 颜色的红色分量([0..1])      * @param green 颜色的绿色分量([0..1])      * @param blue 颜色的蓝色量([0..1])      * @return      */     @ColorInt     public static int rgb(float red, float green, float blue) {         if(red<0) {             red = 0;         }else if(red>1){             red = 1;         }         if(green<0) {             green = 0;         }else if(green>1){             green = 1;         }         if(blue<0) {             blue = 0;         }else if(blue>1){             blue = 1;         }         return 0xff000000 |                 ((int) (red   * 255.0f + 0.5f) << 16) |                 ((int) (green * 255.0f + 0.5f) <<  8) |                 (int) (blue  * 255.0f + 0.5f);     }      /**      * 返回以指定颜色长度编码的红色组件。返回值的范围取决于与指定颜色关联的颜色空间。可以通过调用{@link #colorSpace(long)}来查询颜色空间。      * @param color 要提取其红色通道的长颜色      * @return 具有由指定颜色的颜色空间定义的范围的浮点值      *      * @see #colorSpace(long)      * @see #green(long)      * @see #blue(long)      * @see #alpha(long)      */     public static float red(@ColorLong long color) {         if ((color & 0x3fL) == 0L) return ((color >> 48) & 0xff) / 255.0f;         return toFloat((short) ((color >> 48) & 0xffff));     }      /**      * 返回以指定颜色长度编码的绿色组件。返回值的范围取决于与指定颜色关联的颜色空间。可以通过调用{@link #colorSpace(long)}来查询颜色空间。      * @param color 要提取其绿色通道的长颜色      * @return 具有由指定颜色的颜色空间定义的范围的浮点值      * @see #colorSpace(long)      * @see #red(long)      * @see #blue(long)      * @see #alpha(long)      */     public static float green(@ColorLong long color) {         if ((color & 0x3fL) == 0L) return ((color >> 40) & 0xff) / 255.0f;         return toFloat((short) ((color >> 32) & 0xffff));     }     /**      * 返回以指定颜色长度编码的蓝色组件。返回值的范围取决于与指定颜色关联的颜色空间。可以通过调用{@link #colorSpace(long)}来查询颜色空间。      *      * @param color 要提取其蓝色通道的长颜色      * @return 具有由指定颜色的颜色空间定义的范围的浮点值      * @see #colorSpace(long)      * @see #red(long)      * @see #green(long)      * @see #alpha(long)      */     public static float blue(@ColorLong long color) {         if ((color & 0x3fL) == 0L) return ((color >> 32) & 0xff) / 255.0f;         return  toFloat((short) ((color >> 16) & 0xffff));     }      /**      * 返回以指定颜色长度编码的alpha组件。返回的值始终在范围([0..1])内。      * @param color 要提取其alpha通道的长颜色      * @return 范围为([0..1])的浮点值      * @see #colorSpace(long)      * @see #red(long)      * @see #green(long)      * @see #blue(long)      */     public static float alpha(@ColorLong long color) {        // int c=Color.toArgb(color);         if ((color & 0x3fL) == 0L) return ((color >> 56) & 0xff) / 255.0f;         return ((color >> 6) & 0x3ff) / 1023.0f;     }      /**      * 将指定的长颜色转换为ARGB整型颜色。整型颜色始终位于{@link color space.Named#SRGB SRGB}颜色空间中。这意味着如果需要,将应用颜色空间转换。      * @param color  要转换的长颜色      * @return sRGB颜色空间中的ARGB颜色      */     @ColorInt     public static int toArgb(@ColorLong long color) {         if ((color & 0x3fL) == 0L) return (int) (color >> 32);         float r = red(color);         float g = green(color);         float b = blue(color);         float a = alpha(color);         return ((int) (a * 255.0f + 0.5f) << 24) |                 ((int) (r   * 255.0f + 0.5f) << 16) |                 ((int) (g * 255.0f + 0.5f) <<  8) |                 (int) (b  * 255.0f + 0.5f);     }     /**      * 按指定透明度重新输出      * @param color 需要转换的颜色      * @param alpha 透明度      * @return 返回指定透明度的新颜色      */     public static int toColor(int color,float alpha){         float red=Color.red(color)/255.0f;         float green=Color.green(color)/255.0f;         float blue=Color.blue(color)/255.0f;         return argb(alpha,red,green ,blue );     }     /**      * 按指定透明度重新输出      * @param color 需要转换的颜色      * @param alpha 透明度0-255      * @return 返回指定透明度的新颜色      */     public static int toColor(int color,int alpha){         return argb(alpha,red(color),green(color),blue(color));     }     /**      * <p>将指定的半精度浮点值转换为单精度浮点值。      * @param h 要与此{@code half}对象表示的半精度值进行比较的半精度浮点值      * @return 如果{@code x}在数值上等于{@code y},则为{@code 0};如果{@code x}在数值上小于{@code y},则为小于{@code 0};如果{@code x}在数值上大于{@code y},则为大于{@code 0}      */     public static float toFloat( short h) {         int bits = h & 0xffff;         int s = bits & 0x8000;         int e = (bits >>> 10) & 0x1f;         int m = (bits                        ) & 0x3ff;          int outE = 0;         int outM = 0;          if (e == 0) { // Denormal or 0             if (m != 0) {                 // Convert denorm fp16 into normalized fp32                 float o = Float.intBitsToFloat((126 << 23) + m);                 o -= Float.intBitsToFloat((126 << 23));                 return s == 0 ? o : -o;             }         } else {             outM = m << 13;             if (e == 0x1f) { // Infinite or NaN                 outE = 0xff;                 if (outM != 0) { // SNaNs are quieted                     outM |= 0x400000;                 }             } else {                 outE = e - 15 + 127;             }         }         int out = (s << 16) | (outE << 23) | outM;         return Float.intBitsToFloat(out);     } } 

3、环形选择器源代码类:

import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.SweepGradient; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView;  import java.io.IOException; import java.util.Timer; import java.util.TimerTask;  import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat;  import com.ble.konshine.util.ColorUnit;//这里引用路径工具自己ColorUnit实在的路径进行引用 import com.ble.konshine.R;//属性资源引用,路径根据自己的路径重新引用   public class RingColorPicker extends View {     private final static String TAG="RingColorPicker";     private final static int CENTER_CIRCLE_WIDTH=5;     /**长按超过0.3秒,触发长按事件*/     private static final int LONGPRESSTIME= 300;     /**宽度*/     private int width;     /**高度*/     private int height;     /**圆环的宽*/     private int RingWidth = 20;     /**颜色选择器样式*/     private PickerStyle colorPickerStyle=PickerStyle.MARK_RING_INNER;     /**内圆的半径*/     private float innerRadius;     /**外圆的半径*/     private float outerRadius;     /**圆的圆心坐标*/     private float circleX, circleY;     /**圆环的画笔*/     private Paint paintCircleRing;     /**圆形选择器*/     private Paint paintSelecter;     /**圆形选择器填充色*/     private int colorMarkFill =0xafffffff;     /**圆形选择器描边画笔*/     private Paint paintSelecterStroke;     /**圆形选择器描边*/     private boolean markStroke=false;     /**圆形选择器描边颜色*/     private int colorMarkStroke=0xff000000;     /**选择器圆心坐标*/     private float markPointX, markPointY;     /**默认角度*/     private float angle = 0;     /**选择器自动色*/     private boolean markAutoColor=true;     /**扩散效果透明度*/     private int spreadAlpha=128;     /**选择器圆点边框宽度*/     private int markStrokeWidth=1;     /**色环颜色的发散位置*/     private Shader shader;     /**中间圆画笔,用于显示当前选中的颜色*/     private Paint centerPaint;     /**中心图片*/     private Bitmap centerBitmap=null;     /**着色器颜色*/     private int tintColor=Color.BLACK;     /**着色*/     private boolean isTint=false;     /**图片着色器列表*/     private int[] tintArrayColor;     /**中心图片透明度*/     private int centerImageAlpha=255;     /**中心圆半径*/     private float centerRadius;     /**中心按钮复选状态*/     private boolean checked=false;     /**当前点颜色*/     private int currentColor;     /**中心位图画刷*/     private  Paint centerBitmapPaint;     /**渐变色环参数:红、紫、蓝、青色、绿、黄、红*/     private final int[] mCircleColors =new int[] {             Color.RED ,             Color.YELLOW ,             Color.GREEN ,             Color.CYAN ,             Color.BLUE ,             Color.MAGENTA ,             Color.RED     };     /**冗长等级枚举*/     public enum  PickerStyle{         /**选择器在圆环内%*/         MARK_RING_INNER(0),         /**选择器超出圆环%*/         MARK_RING_OUTER(1),         /**选择器按下是超出圆环*/         MARK_RING_DOWN_OUTER(2);         private int style;         /**选择器样式*/         PickerStyle( int style){             this.style=style;         }         /**获取选择器样式*/         public int getStyle() {             return this.style;         }     }     /**在圆环上按下*/     private boolean isRingDown=false;     /**在选择器上按下*/     private boolean isMarkPointRangeDown=false;     /**用户改变*/     private boolean isFromUser=false;     /**中心按钮按下状态*/     private boolean isButtonClick=false;     /**上一次点击的的坐标*/     private float lastX,lastY;     /**计时器,计时点击时长*/     private Timer timer;     /**长按时间处理*/     private TimerTask timerTaskLongDown;     /**用于存放改变前的角度*/     private float oleAngle=0;     /**用于标识是否使用了长按*/     private boolean isLongClick=false;     /**      * 当进颜色更改时通知客户端的回调。这包括用户通过触摸手势或箭头键/轨迹球发起的更改,以及以编程方式发起的更改。      */     public interface OnRingColorPickerChangeListener {         /**          * 改变通知。          * 客户机可以使用from user参数将用户发起的更改与以编程方式发生的更改区分开来。          * @param ringColorPicker 以改变的RingColorPicker对象          * @param angle 改变的角度值          * @param fromUser 如果进度更改是由用户启动的,则为True。          */          void onChangeListener(RingColorPicker ringColorPicker,float angle,boolean fromUser);         /**          * 通知用户已开始触摸手势。客户端可能希望使用此选项来禁用推进ringColorPicker。          * @param ringColorPicker 开始触摸手势的RingColorPicker          */         void onStartTrackingTouch(RingColorPicker ringColorPicker);          /**          * 通知用户已完成触摸手势。客户端可能希望使用此选项重新启用ringColorPicker。          * @param ringColorPicker 停止触摸手势的RingColorPicker          */         void onStopTrackingTouch(RingColorPicker ringColorPicker);     }      /**      * 颜色选择器中心按钮的选中状态更改时要调用的回调的接口定义。      */     public interface OnCheckedChangeListener{         /**          * 当颜色选择器中心按钮的选中状态更改时调用。          * @param colorPicker 状态已更改的颜色选择器视图。          * @param isChecked 新选中状态。          * @param fromUser 如果进度更改是由用户启动的,则为True。          */         void onCheckedChanged(RingColorPicker colorPicker, boolean isChecked,boolean fromUser);     }     /**定义颜色选择器颜色选择更改通知变量*/     private OnRingColorPickerChangeListener onRingColorPickerChangeListener;     /**定义中心按钮状态改变通知变量*/     private OnCheckedChangeListener onCheckedChangeListener;     /**d定义中心按钮单击事件*/     private OnClickListener onClickListener;     /**定义中心按钮长按事件*/     private OnLongClickListener onLongClickListener;     /**      * 构造函数      * @param context 应用上下文      */     public RingColorPicker(Context context) {        this(context,null);     }     /**      * 构造函数      * @param context 应用上下文      * @param attrs 控件属性集对象      */     public RingColorPicker(Context context, @Nullable AttributeSet attrs) {         this(context,attrs,0);     }     /**      * 构造函数      * @param context 应用上下文      * @param attrs 控件属性集对象      * @param defStyleAttr 默认样式      */     public RingColorPicker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.RingColorPicker);         this.angle=typedArray.getFloat(R.styleable.RingColorPicker_angle,this.angle);         this.colorMarkFill =typedArray.getColor(R.styleable.RingColorPicker_markBackground,this.colorMarkFill );         this.colorMarkStroke=typedArray.getColor(R.styleable.RingColorPicker_markStrokeColor,this.colorMarkStroke);         this.markStroke=typedArray.getBoolean(R.styleable.RingColorPicker_isMarkStroke, this.markStroke);         this.RingWidth=typedArray.getDimensionPixelOffset(R.styleable.RingColorPicker_ringWidth,dp2px(context, this.RingWidth));         this.markAutoColor=typedArray.getBoolean(R.styleable.RingColorPicker_isMarkAutoColor,this.markAutoColor);         this.spreadAlpha=typedArray.getInt(R.styleable.RingColorPicker_spreadAlpha,this.spreadAlpha);         this.markStrokeWidth=typedArray.getDimensionPixelOffset(R.styleable.RingColorPicker_markStrokeWidth,dp2px(context,this.markStrokeWidth));         int resid=typedArray.getResourceId(R.styleable.RingColorPicker_srcCompat,0); //获取 图片资源id         if(resid!=0) {             this.centerBitmap = VectorDrawableToBitmap(resid);  //从资源ID矢量图形转为位图             if (this.centerBitmap == null) {                 this.centerBitmap = BitmapFactory.decodeResource(getResources(), resid);//从图片资源中获取位图             }         }         centerImageAlpha=typedArray.getInt(R.styleable.RingColorPicker_centerImageAlpha,centerImageAlpha);         isTint=typedArray.getResourceId(R.styleable.RingColorPicker_tint,0)!=0;         if(isTint) {             tintColor = typedArray.getColor(R.styleable.RingColorPicker_tint, tintColor);         }         checked=typedArray.getBoolean(R.styleable.RingColorPicker_checked,checked);        // currentColor=typedArray.getColor(R.styleable.RingColorPicker_currentColor,0);         String hexColor=typedArray.getString(R.styleable.RingColorPicker_currentColor);  //通过字符串方式获取16进制颜色字符串         if(hexColor!=null) {   //判断字符串是否为空             //计算当前颜色,             float hsv[] = new float[3];             currentColor=Color.parseColor(hexColor);             ColorUnit.colorToHSV(currentColor, hsv);//得到当前显示的颜色             this.angle=hsv[0]+90;             if(this.angle>360) this.angle-=360;         }else{             //将当前选择器圆点角度转为hsv颜色的标准角度             float tempAngle=this.angle-90;             if(tempAngle<0) tempAngle+=360.0f;             currentColor= ColorUnit.HSVToColor(255,tempAngle,1,1);//这里的角度必须要减90度,因为hsv的0度颜色为红色         }         int mPickerStyle= typedArray.getInteger(R.styleable.RingColorPicker_colorPickerStyle,0);         if(mPickerStyle==0){             this.colorPickerStyle=PickerStyle.MARK_RING_INNER;         }else if(mPickerStyle==1){             this.colorPickerStyle=PickerStyle.MARK_RING_OUTER;         }else if(mPickerStyle==2){             this.colorPickerStyle=PickerStyle.MARK_RING_DOWN_OUTER;         }         init();         typedArray.recycle();     }     @Override     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, heightMeasureSpec);         // RingWidth = dp2px(getContext(), 20);         width = getMeasuredWidth();         height = getMeasuredHeight();         //四边最保留区域(非绘图区,最少保留4给像素)         int paddingLeft,paddingRight;         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {             paddingLeft=(getPaddingStart()==0?getPaddingLeft():getPaddingStart())+4;             paddingRight=(getPaddingEnd()==0?getPaddingRight():getPaddingEnd())+4;         }else{             paddingLeft=getPaddingLeft()+4;             paddingRight=getPaddingRight()+4;         }         int paddingTop=getPaddingTop()+4;         int paddingBottom=getPaddingBottom()+4;         if(colorPickerStyle==PickerStyle.MARK_RING_OUTER ||colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER){             paddingLeft+=RingWidth/2;             paddingRight+=RingWidth/2;             paddingTop+=RingWidth/2;             paddingBottom+=RingWidth/2;         }         int size = ((width-paddingLeft-paddingRight) > (height-paddingTop-paddingBottom)) ? height-paddingTop-paddingBottom : width-paddingLeft-paddingRight; //选择最小         circleX =paddingLeft+(width-paddingLeft-paddingRight)/2;//(width+getPaddingLeft()-getPaddingRight()) / 2;  //确定圆的x坐标中心点         circleY = paddingTop+(height-paddingTop-paddingBottom )/2;//height / 2;   //确定圆的Y坐标中心点         //分辨率适配:获取圆环的宽度 圆环的半径 内部圆的半径         outerRadius=size/2;//-dp2px(getContext(),4);//-barWidth*2;         innerRadius=outerRadius-RingWidth;         shader=new SweepGradient(circleX, circleY, mCircleColors, null);//角度渐变着色器,颜色平均分配         paintCircleRing.setShader(shader);//设置着色器     }     @Override     protected void onDraw(Canvas canvas) {         super.onDraw(canvas);         /***********************画色环*****************************/         Path path=new Path();         RectF outerRect=new RectF(circleX-outerRadius,circleY-outerRadius,circleX+outerRadius,circleY+outerRadius);         RectF innerRect=new RectF(circleX-innerRadius,circleY-innerRadius,circleX+innerRadius,circleY+innerRadius);         //这里内圆和外圆的开始角一定要错开,否则路径无法闭合,填充出来的就不是圆环         path.addArc(outerRect,0,360);         path.arcTo(innerRect,359,-360);         path.close();         canvas.drawPath(path,paintCircleRing);         /******************* 绘制颜色选择器*************************/         setInitMarkToXY(this.angle);         float frameRadius;         if(colorPickerStyle==PickerStyle.MARK_RING_INNER||colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER){             frameRadius =RingWidth/2;         }else{             frameRadius =RingWidth;         }         if(this.markAutoColor) {             paintSelecter.setColor(interpCircleColor(mCircleColors, this.angle));         }         if(colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER && isMarkPointRangeDown){             Paint spreadPaint=new Paint(Paint.ANTI_ALIAS_FLAG);             spreadPaint.setStyle(Paint.Style.FILL);             int spreadColor;             if(this.markAutoColor) {                 spreadColor=interpCircleColor(mCircleColors, this.angle);              }else{                 spreadColor=colorMarkFill;             }             Shader mShader = new RadialGradient(markPointX, markPointY, RingWidth, new int[]{spreadColor, ColorUnit.toColor(spreadColor,30)}, null,Shader.TileMode.CLAMP);             spreadPaint.setShader(mShader);             canvas.drawCircle(markPointX, markPointY, RingWidth, spreadPaint);  //绘制半透明扩散         }else{             canvas.drawCircle(markPointX, markPointY, frameRadius, paintSelecter);//绘制选择器圆点         }         if(markStroke||colorPickerStyle!=PickerStyle.MARK_RING_OUTER) {//绘制选择器边框             float radius=frameRadius-markStrokeWidth/2;//重新计算圆的半径,用于解决线宽向内扩充的问题             canvas.drawCircle(markPointX, markPointY, radius, paintSelecterStroke); //绘制选择器圆点边框         }         /*********************绘制中心按钮*************************/         centerRadius=innerRadius/2;         if(checked) {  //复选状态为选择状态             centerPaint.setShader(new RadialGradient(circleX, circleY, innerRadius, new int[]{currentColor, 0x00ffffff}, null, Shader.TileMode.CLAMP));             centerPaint.setStyle(Paint.Style.FILL);             canvas.drawCircle(circleX, circleY, innerRadius, centerPaint);//画中心圆             centerPaint.setShader(null);             centerPaint.setColor(currentColor);             canvas.drawCircle(circleX, circleY, centerRadius, centerPaint);//画中心圆         }         //绘制中心按钮边框         centerPaint.setStyle(Paint.Style.STROKE);         centerPaint.setColor(0xffffffff);         centerPaint.setStrokeWidth(3);        canvas.drawCircle(circleX,circleY, centerRadius,  centerPaint);//画中心圆边框       if(centerBitmap!=null) {            int imgRadius= (int) (centerRadius / 2);            if(tintArrayColor!=null && tintArrayColor.length>1) {                centerBitmap = getGradientBitmap(centerBitmap,tintArrayColor);                canvas.drawBitmap(centerBitmap, null, new Rect((int) (circleX - imgRadius), (int) (circleY-imgRadius), (int)(circleX + imgRadius), (int) (circleY+imgRadius)), null);            }else{                canvas.drawBitmap(centerBitmap, null, new Rect((int) (circleX - imgRadius), (int) (circleY-imgRadius), (int)(circleX + imgRadius), (int) (circleY+imgRadius)), isTint?centerBitmapPaint:null);//centerBitmapPaint            }        }  //        Paint paint = new Paint(); //        paint.setTextSize(25); //        paint.setColor(Color.RED); // //        paint.setFlags(Paint. UNDERLINE_TEXT_FLAG); //        paint.setColor(Color.GREEN); //        canvas.drawText("My Underline Text", 50, 140, paint);         //canvas.drawText("角度:"+this.angle,20,20,centerPaint);     }     @Override     public boolean dispatchTouchEvent(MotionEvent event) {         float x = event.getX();         float y = event.getY();         if (isPointRange(x,y) || isMarkPointRange(x, y)) {  //如果触摸坐标在圆环或颜色选择器上时             getParent().requestDisallowInterceptTouchEvent(true); //请求请求所有的视图件禁止接收触摸事件         }         return super.dispatchTouchEvent(event);     }     @Override     public boolean onTouchEvent(MotionEvent event) {         float x = event.getX();         float y = event.getY();         switch (event.getAction()) {             case MotionEvent.ACTION_DOWN: //触摸按下                 //判断触摸按下的坐标是否在圆环上                 if (isPointRange(x,y)){                     if(onRingColorPickerChangeListener!=null){                         onRingColorPickerChangeListener.onStartTrackingTouch(this);                     }                     isRingDown=true; //将标志改为触摸按下圆环                     //判断触摸按下的坐标是否非选择器上,不在选择器上就执行旋转操作                     if (!isMarkPointRange(x, y)) {                         this.isFromUser=true;                         if(colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER)                             isMarkPointRangeDown=true;                         setAngle(x, y);   //设置旋转角度                     }else{                         isMarkPointRangeDown=true;                         if(colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER)                             invalidate();                     }                 }else{                     isRingDown=false;  //将标志设置未非圆环上按下                     if (isMarkPointRange(x, y)) {  //这里用于处理选择器圆点大于圆环宽度的情况                         isMarkPointRangeDown=true;                         if(colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER)                             invalidate();                     }                 }                 if(isCenterButton(x,y)) {                     timer=new Timer();//长按计时器                     timerTaskLongDown=new TimerTask() {                         @Override                         public void run() {                             isButtonClick=false;                             if(onLongClickListener!=null){                                 isLongClick=onLongClickListener.onLongClick(RingColorPicker.this);  //触发长按事件                             }                         }                     };                     isButtonClick=true;                     timer.schedule(timerTaskLongDown,LONGPRESSTIME,1000*60*60*24);                     //记录上次点击的位置,用来进行移动的模糊处理                     lastX=x;                     lastY=y;                 }                 break;             case MotionEvent.ACTION_MOVE: //触摸移动                 if(isRingDown) {  //如果为圆环按下状态                     if(isMarkPointRangeDown){ //如果为选择器按下状态                         this.isFromUser=true;                         setAngle(x, y);  //设置旋转角度                     }else {                         if (isMarkPointRange(x, y)) {  //判断触摸按下的坐标是否非选择器上                             isMarkPointRangeDown=true; //将标志改为选择器按下状态                             if(colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER)                                 invalidate();                         }                     }                 }else{                     if(isMarkPointRangeDown){   //处理选择器圆点大于圆环宽度的情况                         this.isFromUser=true;                         setAngle(x, y);  //设置旋转角度                     }                 }                 //处理长按判断                 if(isButtonClick) {                     if (Math.abs(lastX - x) > 20 || Math.abs(lastY - y) > 20) {   //判断是否移动                         isButtonClick=false;                         //取消计时                         if(timerTaskLongDown!=null)  timerTaskLongDown.cancel();                         if(timer!=null) timer.cancel();                     }else{                         return true;                     }                 }                 break;             case MotionEvent.ACTION_UP://触摸弹起                 if(isRingDown||isMarkPointRangeDown){                     if(onRingColorPickerChangeListener!=null){                         onRingColorPickerChangeListener.onStopTrackingTouch(this);                     }                 }                 //if(colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER)                 //计算当前颜色,                 float hsv[]=new float[3];                 ColorUnit.colorToHSV(currentColor,hsv);//得到当前显示的颜色                 //将当前选择器圆点角度转为hsv颜色的标准角度                 float tempAngle=this.angle-90;                 if(tempAngle<0) tempAngle+=360.0f;                 //将当前hsv代表的颜色替换角度后重新生成当前新颜色(这样的目的是只改变色调,饱和度和亮度保存不变)                 currentColor= ColorUnit.HSVToColor(255,tempAngle,hsv[1],hsv[2]);                 if(isCenterButton(x,y) && !isLongClick){                     setChecked(!checked,true);  //将状态取反                     if(onClickListener!=null){   //触发单击事件                         onClickListener.onClick(this);                     }                 }                 invalidate();                 //取消计时                if(timerTaskLongDown!=null)  timerTaskLongDown.cancel();                if(timer!=null) timer.cancel();                 isRingDown=false;                 isMarkPointRangeDown=false;                 isButtonClick=false;                 isLongClick=false;                 break;             case MotionEvent.ACTION_CANCEL: //取消操作                 Log.e("onTouchEvent","取消操作");                 break;         }         return true;     }     /**************************公共属性及方法******************************/     /**      * 设置侦听器以接收RingColorPicker更改的通知。还提供用户在RingColorPicker中启动和停止触摸手势的通知。      * @param listener 通知侦听器      */     public void setOnRingColorPickerChangeListener(@Nullable OnRingColorPickerChangeListener listener){         this.onRingColorPickerChangeListener = listener;     }     /**      * 注册此按钮的选中状态更改时要调用的回调。      * @param listener 调用选中状态更改的回调      */     public void setOnCheckedChangeListener( @Nullable OnCheckedChangeListener listener){         this.onCheckedChangeListener=listener;     }     /**      * 注册颜色选择器中心按钮单击事件      * @param onClickListener 将运行的回调      */     @Override     public void setOnClickListener(OnClickListener onClickListener) {         this.onClickListener = onClickListener;     }     /**      * 注册颜色选择器中心按钮长按事件      * @param onLongClickListener 将运行的回调      */     @Override     public void setOnLongClickListener(OnLongClickListener onLongClickListener) {         this.onLongClickListener = onLongClickListener;     }      /**      * 设置选择器再圆环的角度      * @param angle 角度      */     public void setAngle(float angle) {         this.angle = angle;         this.isFromUser=false;         invalidate();         ImageView imageView;     }     /**获取选择器再圆环上的角度*/     public float getAngle() {         return angle;     }     /**      * 设置圆环宽度      * @param ringWidth      */     public void setRingWidth(int ringWidth) {         RingWidth = dp2px(getContext(),ringWidth);         invalidate();     }    /**获取圆环宽度*/     public int getRingWidth() {         return RingWidth;     }     /**      * 设置选择器背景颜色      * @param color 颜色值      */     public void setMarkBackground(int color){         this.colorMarkFill =color;         paintSelecter.setColor(colorMarkFill );         invalidate();     }     /**      * 设置选择器背景颜色      * @param color Color颜色对象      */     public void setMarkBackground(Color color){         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {             setMarkBackground(color.toArgb());         }     }     /**      * 设置选择器背景颜色      * @param colorString 16进制颜色字符串。如"#RRGGBB 或 #AARRGGBB"      */     public void setMarkBackground(String colorString){         try {             int color=Color.parseColor(colorString);             setMarkBackground(color);         } catch (Exception e) {             Log.e("setSelecterBackground",e.getMessage());         }     }     /**获取选择器背景色*/     public int getMarkBackground(){         return colorMarkFill ;     }     /**      * 设置选择器边框杨色      * @param color 颜色值      */     public void setMarkStrokeColor(int color){         this.colorMarkStroke=color;         paintSelecterStroke.setColor(colorMarkStroke);         invalidate();     }     /**      * 设置选择器边框杨色      * @param color Color颜色对象      */     public void setMarkStrokeColor(Color color){         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {             this.setMarkStrokeColor( color.toArgb());        }     }     /**      * 设置选择器边框杨色      * @param colorString 16进制颜色字符串。如"#RRGGBB 或 #AARRGGBB"      */     public void setMarkStrokeColor(String colorString){         try {             int color=Color.parseColor(colorString);             setMarkStrokeColor(color);         } catch (Exception e) {             Log.e("setSelecterStroke",e.getMessage());         }     }     /**获取选择器边框颜色*/     public int getMarkStrokeColor(){         return colorMarkStroke;     }     /**      * 设置选择器边框(只对ColorPickerStyle=MARK_RING_OUTER有效,另外两种样式必须具有边框)      * @param stroke      */     public void setMarkStroke(boolean stroke){         this.markStroke=stroke;         invalidate();     }    /**获取选择器边框*/     public boolean isMarkStroke() {         return markStroke;     }     /**      * 设置选择器样式      * @param colorPickerStyle PickerStyle枚举      */     public void setColorPickerStyle(PickerStyle colorPickerStyle) {         this.colorPickerStyle = colorPickerStyle;         ////////////////////////////重新初始化以下参数/////////////////////////////////////////////////         //四边最保留区域(非绘图区,最少保留4给像素)         int paddingLeft,paddingRight;         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {             paddingLeft=(getPaddingStart()==0?getPaddingLeft():getPaddingStart())+4;             paddingRight=(getPaddingEnd()==0?getPaddingRight():getPaddingEnd())+4;         }else{             paddingLeft=getPaddingLeft()+4;             paddingRight=getPaddingRight()+4;         }         int paddingTop=getPaddingTop()+4;         int paddingBottom=getPaddingBottom()+4;         if(colorPickerStyle==PickerStyle.MARK_RING_OUTER ||colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER){             paddingLeft+=RingWidth/2;             paddingRight+=RingWidth/2;             paddingTop+=RingWidth/2;             paddingBottom+=RingWidth/2;         }         int size = ((width-paddingLeft-paddingRight) > (height-paddingTop-paddingBottom)) ? height-paddingTop-paddingBottom : width-paddingLeft-paddingRight; //选择最小         circleX =paddingLeft+(width-paddingLeft-paddingRight)/2;//(width+getPaddingLeft()-getPaddingRight()) / 2;  //确定圆的x坐标中心点         circleY = paddingTop+(height-paddingTop-paddingBottom )/2;//height / 2;   //确定圆的Y坐标中心点         //分辨率适配:获取圆环的宽度 圆环的半径 内部圆的半径         outerRadius=size/2;//-dp2px(getContext(),4);//-barWidth*2;         innerRadius=outerRadius-RingWidth;         shader=new SweepGradient(circleX, circleY, mCircleColors, null);//角度渐变着色器         paintCircleRing.setShader(shader);//设置着色器          invalidate();     }     /**获取选择器样式*/     public PickerStyle getColorPickerStyle() {         return colorPickerStyle;     }      /**      * 使用选择器自动色      * @param autoColor      */     public void setMarkAutoColor(boolean autoColor){         this.markAutoColor=autoColor;         invalidate();     }     /**获取选择器自动颜色状态 */     public boolean isMarkAutoColor() {         return markAutoColor;     }      /**      * 设置扩散效果透明度      * @param alpha 透明度(0-255之间)      */     public void setSpreadAlpha(int alpha) {         if(alpha<0)             alpha=0;         else if(alpha>255)             alpha=255;         this.spreadAlpha = alpha;         invalidate();     }     /**      * 设置扩散效果透明度      * @param alpha 透明度(0-1之间)      */     public void setSpreadAlpha(float alpha) {         if(alpha<0)             alpha=0;         else if(alpha>1)             alpha=1;         setSpreadAlpha((int) (alpha*255));     }     /**获取扩散效果透明度*/     public int getSpreadAlpha() {         return spreadAlpha;     }     /**      * 设置选择器圆点边框宽度      * @param markStrokeWidth      */     public void setMarkStrokeWidth(int markStrokeWidth) {         this.markStrokeWidth = dp2px(getContext(),markStrokeWidth);         paintSelecterStroke.setStrokeWidth(this.markStrokeWidth);         invalidate();     }     /**获取选择器圆点边框宽度*/     public int getMarkStrokeWidth() {         return markStrokeWidth;     }      /**      * 设置中心图片位图      * @param bm 位图      */     public void setCenterImageBitmap(Bitmap bm){         centerBitmap=bm;         invalidate();     }      /**      * 设置中心图片Drawable      * @param drawable      */     public void setCenterImageDrawable(Drawable drawable){         setCenterImageBitmap(DrawableToBitmap(drawable));     }       /**      * 设置中心图片资源ID      * @param resId 资源id      */     public void setCenterImageResource(int resId){         setCenterImageBitmap(BitmapFactory.decodeResource(getResources(),resId));     }      /**      * 设置中心图片图标      * @param icon 图标      */     public void setImageIcon(Icon icon){         if ( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M ) {             BitmapDrawable bd=(BitmapDrawable) icon.loadDrawable(this.getContext());             setCenterImageBitmap(bd.getBitmap());         }     }     /**      * 设置中心图片uri地址      * @param uri      */     public void setCenterImageURI(Uri uri){         try {             Bitmap bm= MediaStore.Images.Media.getBitmap(this.getContext().getContentResolver(), uri);             setCenterImageBitmap(bm);         } catch (IOException e) {             e.printStackTrace();             Log.e(TAG,e.getMessage());         }     }     /**获取中心图标位图*/     public Bitmap getCenterImageBitmap(){         return centerBitmap;     }     /**      * 设置中心图片透明度      * @param alpha 透明度(0-255)      */     public void setCenterImageAlpha(int alpha){         centerImageAlpha=alpha;         centerBitmapPaint .setAlpha( this.centerImageAlpha);         invalidate();     }     /**获取中心图片透明度*/     public float getCenterImageAlpha() {         return centerImageAlpha;     }      /**      * 设置中心按钮复选状态      * @param checked 选择状态      */     public void setChecked(boolean checked) {         setChecked(checked,false);         invalidate();     }     /**获取中心按钮选择状态*/     public boolean isChecked() {         return checked;     }     /**      * 设置着色器颜色      * @param tintColor      */     public void setTintColor(int tintColor) {         this.tintColor = tintColor;         centerBitmapPaint.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));         isTint=true;         invalidate();     }     /**      * 设置着色器颜色      * @param tintColor      */     public void setTintColor(Color tintColor) {         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {             if(tintColor!=null) {                 setTintColor(tintColor.toArgb());             }else{                 isTint=false;                 invalidate();             }         }     }     /**      * 设置着色器颜色      * @param colorString      */     public void setTintColor(String colorString) {         try {             setTintColor(Color.parseColor(colorString));         } catch (Exception e) {             Log.e("setTintColor",e.getMessage());             isTint=false;             invalidate();         }     }   /**获取着色器颜色**/     public int getTintColor() {         return tintColor;     }      /**      * 设置图片着色器渐变色      * @param arrayColor      */     public void setTintArrayColor(int[] arrayColor){         tintArrayColor=arrayColor;         invalidate();     }     /**获取着色器渐变色*/     public int[] getTintArrayColor() {         return tintArrayColor;     }     /**      * 设置当前颜色      * @param color 需要改变的当前颜色      */     public void setCurrentColor(int color) {         this.currentColor = color;         float hsv[]=new float[3];         ColorUnit.colorToHSV(this.currentColor,hsv);//得到当前显示的颜色         this.angle=hsv[0]+90;         if(this.angle>360) this.angle-=360;         this.isFromUser=false;         invalidate();     }     /**      * 设置当前颜色      * @param color 需要改变的当前颜色      */     public void setCurrentColor(Color color) {         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {             setCurrentColor(color.toArgb());         }     }     /**      * 设置当前颜色      * @param colorString 需要改变的当前颜色      */     public void setCurrentColor(String colorString) {         try {             setCurrentColor(Color.parseColor(colorString));         } catch (Exception e) {             Log.e("setCurrentColor",e.getMessage());         }     }     /**      * 通过HSV设置当前颜色      * @param hsv  3元素数组。      *  <ul>      *  <li>hsv[0]是色调([0..360[)</li>      *  <li>hsv[1]色饱和([0…1])</li>      *  <li>hsv[2]是值([0…1])</li>      *  </ul>      */     public void setCurrentColor(float[] hsv){         setCurrentColor(ColorUnit.HSVToColor(hsv));     }     /**      * 通过HSV设置当前颜色      * @param hue 色调([0..360[)      * @param saturation 色饱和([0…1])      * @param value 亮度值([0…1])      */     public void setCurrentColor(float hue,float saturation,float value){         setCurrentColor(ColorUnit.HSVToColor(hue,saturation,value));     }    /**获取当前颜色**/     public int getCurrentColor() {         return currentColor;     }      /**      * 获取渐变混色位图      * @param drawableId 资源ID      * @param colors 渐变颜色数组      * @return      */     public  Bitmap getGradientBitmap( int drawableId, int[] colors) {         //android不允许直接修改res里面的图片,所以要用copy方法         Bitmap bitmap = BitmapFactory.decodeResource(getResources(), drawableId)                 .copy(Bitmap.Config.ARGB_8888, true);         addGradient(bitmap, colors);         return bitmap;     }     /**      * 获取渐变混色位图      * @param bitmap 需要渐变混色的位图      * @param colors 渐变颜色数组      * @return      */     public  Bitmap getGradientBitmap( Bitmap bitmap, int[] colors) {         Bitmap tempbitmap=bitmap.copy(Bitmap.Config.ARGB_8888, true);         addGradient(tempbitmap, colors);         return tempbitmap;     }     /***********************所有方法****************************/     /**      * 初始化      */     private void init() {         // 渐变色环参数         paintCircleRing = new Paint(Paint.ANTI_ALIAS_FLAG);         paintCircleRing.setAntiAlias(true);         paintCircleRing.setStyle(Paint.Style.FILL);          //选择器         paintSelecter = new Paint(Paint.ANTI_ALIAS_FLAG);         paintSelecter.setColor(colorMarkFill );         paintSelecter.setAntiAlias(true);         paintSelecter.setStrokeWidth(10);         //选择器描边画笔        // if(markStroke||colorPickerStyle!=PickerStyle.MARK_RING_OUTER) {//绘制选择器边框             paintSelecterStroke = new Paint(Paint.ANTI_ALIAS_FLAG);//创建画笔,并边缘平滑             paintSelecterStroke.setColor(colorMarkStroke);             paintSelecterStroke.setStyle(Paint.Style.STROKE);             paintSelecterStroke.setStrokeWidth(this.markStrokeWidth);        // }         //初始化中心圆的Paint对象         centerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);         centerPaint.setAntiAlias(true);        // centerPaint.setColor(centerCircleColor);         centerPaint.setStrokeWidth(CENTER_CIRCLE_WIDTH);          centerBitmapPaint = new Paint();         centerBitmapPaint .setStyle( Paint.Style.STROKE );         centerBitmapPaint .setAlpha( this.centerImageAlpha);         centerBitmapPaint.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));     }     /**      * dp转像素      * @param context 应用上下文      * @param dpVal 需要转换的dp值      * @return 返回像素未单位的值      */     private static int dp2px(Context context, float dpVal) {         return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,                 dpVal, context.getResources().getDisplayMetrics());     }     /**      * 设置选择器坐标      * @param angle 选择器实在的坐标      */     private void setInitMarkToXY(float angle) {         markPointX = (float) (circleX + (outerRadius- RingWidth/2)* Math.sin(angle * Math.PI / 180));         markPointY = (float) (circleY - (outerRadius- RingWidth/2) * Math.cos(angle * Math.PI / 180));         if(onRingColorPickerChangeListener!=null && oleAngle!=angle){             onRingColorPickerChangeListener.onChangeListener(this,this.angle,this.isFromUser);             oleAngle=angle;         }         this.isFromUser=false;     }      /**      * 返回指定坐标是否再选择器上      * @param x      * @param y      * @return true 在选择器上,false 不在选择器上      */     private boolean isMarkPointRange(float x, float y) {         float centralOffset= (float) Math.sqrt(Math.pow(x-markPointX,2)+Math.pow(y-markPointY,2));//计算指定点到圆心偏移量         if(colorPickerStyle==PickerStyle.MARK_RING_INNER||colorPickerStyle==PickerStyle.MARK_RING_DOWN_OUTER) {             return centralOffset <= (RingWidth / 2);         }else{             return centralOffset <= RingWidth ;         }     }      /**      * 指定坐标是否在中心按钮上      * @param x      * @param y      * @return true 在按钮上,false 不在      */     private boolean isCenterButton(float x,float y){         float centralOffset= (float) Math.sqrt(Math.pow(x-circleX,2)+Math.pow(y-circleY,2));//计算指定点到圆心偏移量         return centralOffset<=innerRadius/2;     }     /**      * 指定坐标是否在圆环上      * @param x      * @param y      * @return true 再圆环上,false 不在圆环上      */     private boolean isPointRange(float x,float y){         float centralOffset= (float) Math.sqrt(Math.pow(x-circleX,2)+Math.pow(y-circleY,2));//计算指定点到圆心偏移量         return centralOffset>=innerRadius && centralOffset<=outerRadius;     }      /**      * 根据指定坐标设置选择器旋转角度      * @param x      * @param y      */     private void setAngle(float x,float y) {         markPointX = (float) (circleX + outerRadius * Math.cos(Math.atan2(x - circleX, circleY - y) - (Math.PI / 2)));         markPointY = (float) (circleY + outerRadius * Math.sin(Math.atan2(x - circleX, circleY - y) - (Math.PI / 2)));         float degrees = (float) ((float) ((Math.toDegrees(Math.atan2(x - circleX, circleY - y)) + 360.0)) % 360.0);         // 注意:为负数要加360°         if (degrees < 0)             degrees += 2 * Math.PI;         //角度四舍五入         this.angle = Math.round(degrees);         invalidate(); //刷新ui     }     /**      * 设置中心按钮复选状态      * @param checked 选择状态      * @param isFromUser 用户改变      */     private void setChecked(boolean checked,boolean isFromUser) {         this.checked = checked;         if(onCheckedChangeListener!=null){             onCheckedChangeListener.onCheckedChanged(this,checked,isFromUser);         }     }     /**      * 获取圆环上颜色      * @param colors 圆环上面使用到的颜色数组      * @param angle 角度      * @return 返回int颜色      */     private int interpCircleColor(int colors[], float angle) {         angle -= 90;         if (angle < 0)             angle += 360;         float p = angle * (colors.length - 1) / 360;         int i = (int) p;         p -= i;         int c0 = colors[i];         int c1 = colors[i + 1];         int a = ave(Color.alpha(c0), Color.alpha(c1), p);         int r = ave(Color.red(c0), Color.red(c1), p);         int g = ave(Color.green(c0), Color.green(c1), p);         int b = ave(Color.blue(c0), Color.blue(c1), p);         return Color.argb(a, r, g, b);     }     private int ave(int s, int d, float p) {         return s + Math.round(p * (d - s));     }     /**      * Drawable转位图      * @param drawable      * @return      */     private Bitmap DrawableToBitmap(Drawable drawable){         BitmapDrawable bd=null;         try {              bd = (BitmapDrawable) drawable;         } catch (Exception e) {             e.printStackTrace();         }         if(bd!=null) {             return bd.getBitmap();         }else{             int width = drawable.getIntrinsicWidth();             int height = drawable.getIntrinsicHeight();             Bitmap bitmap = Bitmap.createBitmap(width, height,                     drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888: Bitmap.Config.RGB_565);             Canvas canvas = new Canvas(bitmap);             drawable.setBounds(0,0,width,height);             drawable.draw(canvas);             return bitmap;         }     }      /**      * 从资源ID中的矢量图转位图      * @param resId 资源id      * @return      */     private Bitmap VectorDrawableToBitmap(int resId){         Drawable drawable = ContextCompat.getDrawable(getContext(),resId);         drawable = (DrawableCompat.wrap(drawable)).mutate();         return DrawableToBitmap(drawable);     }     /**      * 给位图添加线形着色      * @param originalBitmap 需要着色的旧位图      * @param colors 颜色数组,如果为null或数组长度为0,默认着#ff9900色      * @return 返回着色后的位图      */     private  Bitmap addGradient(Bitmap originalBitmap, int[] colors) {//给originalBitmap着渐变色         if (colors == null || colors.length == 0) {//默认色处理             colors = new int[]{Color.parseColor("#ff9900"), Color.parseColor("#ff9900")};         } else if (colors.length == 1) {//单色处理             int[] newColor = new int[]{colors[0], colors[0]};             colors = newColor;         }         int width = originalBitmap.getWidth();         int height = originalBitmap.getHeight();          Canvas canvas = new Canvas(originalBitmap);//Canvas中Bitmap是用来保存像素,相当于画纸         Paint paint = new Paint();         LinearGradient shader = new LinearGradient(0, 0, width, height, colors, null, Shader.TileMode.CLAMP);//shader:着色器,线性着色器设置渐变从左上坐标到右下坐标         paint.setShader(shader);//设置着色器         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//设置图像混合模式         canvas.drawRect(0, 0, width, height, paint);         return originalBitmap;     } } 

效果如图:

Android圆环颜色选择器
Android圆环颜色选择器
Android圆环颜色选择器

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/898126.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐