Android 颜色选择器(ColorPicker)


因为画图板中需要使用颜色选择器. 去查了下api demo, 发现有现成的ColorPickerDialog, 但是功能比较简单, 主要是无法选择黑色和白色. 之后也去网上找了下, 倒是发现了几个, 但是用着感觉不太好.就想着自己重写个好了.

先上图

1.测试界面

Android 颜色选择器(ColorPicker)

2. 调色板对话框

 

Android 颜色选择器(ColorPicker)

3. 选择颜色

 

Android 颜色选择器(ColorPicker)

4.改变字体颜色 

 

Android 颜色选择器(ColorPicker)


 

调色板对话框

ColorPickerDialog.java

Java代码

  1. package com.dwood.paintdemo;   
  2.   
  3. import Android.app.Dialog;   
  4. import android.content.Context;   
  5. import android.graphics.Canvas;   
  6. import android.graphics.Color;   
  7. import android.graphics.LinearGradient;   
  8. import android.graphics.Paint;   
  9. import android.graphics.RectF;   
  10. import android.graphics.Shader;   
  11. import android.graphics.SweepGradient;   
  12. import android.os.Bundle;   
  13. import android.util.Log;   
  14. import android.view.MotionEvent;   
  15. import android.view.View;   
  16. import android.view.WindowManager;   
  17.   
  18. public class ColorPickerDialog extends Dialog {   
  19.     private final boolean debug = true;   
  20.     private final String TAG = "ColorPicker";   
  21.        
  22.     Context context;   
  23.     private String title;//标题   
  24.     private int mInitialColor;//初始颜色   
  25.     private OnColorChangedListener mListener;   
  26.   
  27.     /**  
  28.      * 初始颜色黑色  
  29.      * @param context  
  30.      * @param title 对话框标题  
  31.      * @param listener 回调  
  32.      */  
  33.     public ColorPickerDialog(Context context, String title,    
  34.             OnColorChangedListener listener) {   
  35.         this(context, Color.BLACK, title, listener);   
  36.     }   
  37.        
  38.     /**  
  39.      *   
  40.      * @param context  
  41.      * @param initialColor 初始颜色  
  42.      * @param title 标题  
  43.      * @param listener 回调  
  44.      */  
  45.     public ColorPickerDialog(Context context, int initialColor,    
  46.             String title, OnColorChangedListener listener) {   
  47.         super(context);   
  48.         this.context = context;   
  49.         mListener = listener;   
  50.         mInitialColor = initialColor;   
  51.         this.title = title;   
  52.     }   
  53.   
  54.     @Override  
  55.     protected void onCreate(Bundle savedInstanceState) {   
  56.         super.onCreate(savedInstanceState);   
  57.         WindowManager manager = getWindow().getWindowManager();   
  58.         int height = (int) (manager.getDefaultDisplay().getHeight() * 0.5f);   
  59.         int width = (int) (manager.getDefaultDisplay().getWidth() * 0.7f);   
  60.         ColorPickerView myView = new ColorPickerView(context, height, width);   
  61.         setContentView(myView);   
  62.         setTitle(title);   
  63.     }   
  64.        
  65.     private class ColorPickerView extends View {   
  66.         private Paint mPaint;//渐变色环画笔   
  67.         private Paint mCenterPaint;//中间圆画笔   
  68.         private Paint mLinePaint;//分隔线画笔   
  69.         private Paint mRectPaint;//渐变方块画笔   
  70.            
  71.         private Shader rectShader;//渐变方块渐变图像   
  72.         private float rectLeft;//渐变方块左x坐标   
  73.         private float rectTop;//渐变方块右x坐标   
  74.         private float rectRight;//渐变方块上y坐标   
  75.         private float rectBottom;//渐变方块下y坐标   
  76.            
  77.         private final int[] mCircleColors;//渐变色环颜色   
  78.         private final int[] mRectColors;//渐变方块颜色   
  79.            
  80.         private int mHeight;//View高   
  81.         private int mWidth;//View宽   
  82.         private float r;//色环半径(paint中部)   
  83.         private float centerRadius;//中心圆半径   
  84.            
  85.         private boolean downInCircle = true;//按在渐变环上   
  86.         private boolean downInRect;//按在渐变方块上   
  87.         private boolean highlightCenter;//高亮   
  88.         private boolean highlightCenterLittle;//微亮   
  89.            
  90.         public ColorPickerView(Context context, int height, int width) {   
  91.             super(context);   
  92.             this.mHeight = height - 36;   
  93.             this.mWidth = width;   
  94.             setMinimumHeight(height - 36);   
  95.             setMinimumWidth(width);   
  96.                
  97.             //渐变色环参数   
  98.             mCircleColors = new int[] {0xFFFF00000xFFFF00FF0xFF0000FF,    
  99.                     0xFF00FFFF0xFF00FF00,0xFFFFFF000xFFFF0000};   
  100.             Shader s = new SweepGradient(00, mCircleColors, null);   
  101.             mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);   
  102.             mPaint.setShader(s);   
  103.             mPaint.setStyle(Paint.Style.STROKE);   
  104.             mPaint.setStrokeWidth(50);   
  105.             r = width / 2 * 0.7f - mPaint.getStrokeWidth() * 0.5f;   
  106.                
  107.             //中心圆参数   
  108.             mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);   
  109.             mCenterPaint.setColor(mInitialColor);   
  110.             mCenterPaint.setStrokeWidth(5);   
  111.             centerRadius = (r - mPaint.getStrokeWidth() / 2 ) * 0.7f;   
  112.                
  113.             //边框参数   
  114.             mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);   
  115.             mLinePaint.setColor(Color.parseColor("#72A1D1"));   
  116.             mLinePaint.setStrokeWidth(4);   
  117.                
  118.             //黑白渐变参数   
  119.             mRectColors = new int[]{0xFF000000, mCenterPaint.getColor(), 0xFFFFFFFF};   
  120.             mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);   
  121.             mRectPaint.setStrokeWidth(5);   
  122.             rectLeft = -r - mPaint.getStrokeWidth() * 0.5f;   
  123.             rectTop = r + mPaint.getStrokeWidth() * 0.5f +    
  124.                     mLinePaint.getStrokeMiter() * 0.5f + 15;   
  125.             rectRight = r + mPaint.getStrokeWidth() * 0.5f;   
  126.             rectBottom = rectTop + 50;   
  127.         }   
  128.   
  129.         @Override  
  130.         protected void onDraw(Canvas canvas) {   
  131.             //移动中心   
  132.             canvas.translate(mWidth / 2, mHeight / 2 - 50);   
  133.             //画中心圆   
  134.             canvas.drawCircle(00, centerRadius,  mCenterPaint);   
  135.             //是否显示中心圆外的小圆环   
  136.             if (highlightCenter || highlightCenterLittle) {   
  137.                 int c = mCenterPaint.getColor();   
  138.                 mCenterPaint.setStyle(Paint.Style.STROKE);   
  139.                 if(highlightCenter) {   
  140.                     mCenterPaint.setAlpha(0xFF);   
  141.                 }else if(highlightCenterLittle) {   
  142.                     mCenterPaint.setAlpha(0x90);   
  143.                 }   
  144.                 canvas.drawCircle(00,    
  145.                         centerRadius + mCenterPaint.getStrokeWidth(),  mCenterPaint);   
  146.                    
  147.                 mCenterPaint.setStyle(Paint.Style.FILL);   
  148.                 mCenterPaint.setColor(c);   
  149.             }   
  150.             //画色环   
  151.             canvas.drawOval(new RectF(-r, -r, r, r), mPaint);   
  152.             //画黑白渐变块   
  153.             if(downInCircle) {   
  154.                 mRectColors[1] = mCenterPaint.getColor();   
  155.             }   
  156.             rectShader = new LinearGradient(rectLeft, 0, rectRight, 0, mRectColors, null, Shader.TileMode.MIRROR);   
  157.             mRectPaint.setShader(rectShader);   
  158.             canvas.drawRect(rectLeft, rectTop, rectRight, rectBottom, mRectPaint);   
  159.             float offset = mLinePaint.getStrokeWidth() / 2;   
  160.             canvas.drawLine(rectLeft - offset, rectTop - offset * 2,    
  161.                     rectLeft - offset, rectBottom + offset * 2, mLinePaint);//左   
  162.             canvas.drawLine(rectLeft - offset * 2, rectTop - offset,    
  163.                     rectRight + offset * 2, rectTop - offset, mLinePaint);//上   
  164.             canvas.drawLine(rectRight + offset, rectTop - offset * 2,    
  165.                     rectRight + offset, rectBottom + offset * 2, mLinePaint);//右   
  166.             canvas.drawLine(rectLeft - offset * 2, rectBottom + offset,    
  167.                     rectRight + offset * 2, rectBottom + offset, mLinePaint);//下   
  168.             super.onDraw(canvas);   
  169.         }   
  170.            
  171.         @Override  
  172.         public boolean onTouchEvent(MotionEvent event) {   
  173.             float x = event.getX() - mWidth / 2;   
  174.             float y = event.getY() - mHeight / 2 + 50;   
  175.             boolean inCircle = inColorCircle(x, y,    
  176.                     r + mPaint.getStrokeWidth() / 2, r - mPaint.getStrokeWidth() / 2);   
  177.             boolean inCenter = inCenter(x, y, centerRadius);   
  178.             boolean inRect = inRect(x, y);   
  179.                
  180.             switch (event.getAction()) {   
  181.                 case MotionEvent.ACTION_DOWN:   
  182.                     downInCircle = inCircle;   
  183.                     downInRect = inRect;   
  184.                     highlightCenter = inCenter;   
  185.                 case MotionEvent.ACTION_MOVE:   
  186.                     if(downInCircle && inCircle) {//down按在渐变色环内, 且move也在渐变色环内   
  187.                         float angle = (float) Math.atan2(y, x);   
  188.                         float unit = (float) (angle / (2 * Math.PI));   
  189.                         if (unit < 0) {   
  190.                             unit += 1;   
  191.                         }   
  192.                         mCenterPaint.setColor(interpCircleColor(mCircleColors, unit));   
  193.                         if(debug) Log.v(TAG, "色环内, 坐标: " + x + "," + y);   
  194.                     }else if(downInRect && inRect) {//down在渐变方块内, 且move也在渐变方块内   
  195.                         mCenterPaint.setColor(interpRectColor(mRectColors, x));   
  196.                     }   
  197.                     if(debug) Log.v(TAG, "[MOVE] 高亮: " + highlightCenter + "微亮: " + highlightCenterLittle + " 中心: " + inCenter);   
  198.                     if((highlightCenter && inCenter) || (highlightCenterLittle && inCenter)) {//点击中心圆, 当前移动在中心圆   
  199.                         highlightCenter = true;   
  200.                         highlightCenterLittle = false;   
  201.                     } else if(highlightCenter || highlightCenterLittle) {//点击在中心圆, 当前移出中心圆   
  202.                         highlightCenter = false;   
  203.                         highlightCenterLittle = true;   
  204.                     } else {   
  205.                         highlightCenter = false;   
  206.                         highlightCenterLittle = false;   
  207.                     }   
  208.                     invalidate();   
  209.                     break;   
  210.                 case MotionEvent.ACTION_UP:   
  211.                     if(highlightCenter && inCenter) {//点击在中心圆, 且当前启动在中心圆   
  212.                         if(mListener != null) {   
  213.                             mListener.colorChanged(mCenterPaint.getColor());   
  214.                             ColorPickerDialog.this.dismiss();   
  215.                         }   
  216.                     }   
  217.                     if(downInCircle) {   
  218.                         downInCircle = false;   
  219.                     }   
  220.                     if(downInRect) {   
  221.                         downInRect = false;   
  222.                     }   
  223.                     if(highlightCenter) {   
  224.                         highlightCenter = false;   
  225.                     }   
  226.                     if(highlightCenterLittle) {   
  227.                         highlightCenterLittle = false;   
  228.                     }   
  229.                     invalidate();   
  230.                     break;   
  231.             }   
  232.             return true;   
  233.         }   
  234.   
  235.         @Override  
  236.         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   
  237.             super.onMeasure(mWidth, mHeight);   
  238.         }   
  239.   
  240.         /**  
  241.          * 坐标是否在色环上  
  242.          * @param x 坐标  
  243.          * @param y 坐标  
  244.          * @param outRadius 色环外半径  
  245.          * @param inRadius 色环内半径  
  246.          * @return  
  247.          */  
  248.         private boolean inColorCircle(float x, float y, float outRadius, float inRadius) {   
  249.             double outCircle = Math.PI * outRadius * outRadius;   
  250.             double inCircle = Math.PI * inRadius * inRadius;   
  251.             double fingerCircle = Math.PI * (x * x + y * y);   
  252.             if(fingerCircle < outCircle && fingerCircle > inCircle) {   
  253.                 return true;   
  254.             }else {   
  255.                 return false;   
  256.             }   
  257.         }   
  258.            
  259.         /**  
  260.          * 坐标是否在中心圆上  
  261.          * @param x 坐标  
  262.          * @param y 坐标  
  263.          * @param centerRadius 圆半径  
  264.          * @return  
  265.          */  
  266.         private boolean inCenter(float x, float y, float centerRadius) {   
  267.             double centerCircle = Math.PI * centerRadius * centerRadius;   
  268.             double fingerCircle = Math.PI * (x * x + y * y);   
  269.             if(fingerCircle < centerCircle) {   
  270.                 return true;   
  271.             }else {   
  272.                 return false;   
  273.             }   
  274.         }   
  275.            
  276.         /**  
  277.          * 坐标是否在渐变色中  
  278.          * @param x  
  279.          * @param y  
  280.          * @return  
  281.          */  
  282.         private boolean inRect(float x, float y) {   
  283.             if( x <= rectRight && x >=rectLeft && y <= rectBottom && y >=rectTop) {   
  284.                 return true;   
  285.             } else {   
  286.                 return false;   
  287.             }   
  288.         }   
  289.            
  290.         /**  
  291.          * 获取圆环上颜色  
  292.          * @param colors  
  293.          * @param unit  
  294.          * @return  
  295.          */  
  296.         private int interpCircleColor(int colors[], float unit) {   
  297.             if (unit <= 0) {   
  298.                 return colors[0];   
  299.             }   
  300.             if (unit >= 1) {   
  301.                 return colors[colors.length - 1];   
  302.             }   
  303.                
  304.             float p = unit * (colors.length - 1);   
  305.             int i = (int)p;   
  306.             p -= i;   
  307.   
  308.             // now p is just the fractional part [0...1) and i is the index   
  309.             int c0 = colors[i];   
  310.             int c1 = colors[i+1];   
  311.             int a = ave(Color.alpha(c0), Color.alpha(c1), p);   
  312.             int r = ave(Color.red(c0), Color.red(c1), p);   
  313.             int g = ave(Color.green(c0), Color.green(c1), p);   
  314.             int b = ave(Color.blue(c0), Color.blue(c1), p);   
  315.                
  316.             return Color.argb(a, r, g, b);   
  317.         }   
  318.            
  319.         /**  
  320.          * 获取渐变块上颜色  
  321.          * @param colors  
  322.          * @param x  
  323.          * @return  
  324.          */  
  325.         private int interpRectColor(int colors[], float x) {   
  326.             int a, r, g, b, c0, c1;   
  327.             float p;   
  328.             if (x < 0) {   
  329.                 c0 = colors[0];    
  330.                 c1 = colors[1];   
  331.                 p = (x + rectRight) / rectRight;   
  332.             } else {   
  333.                 c0 = colors[1];   
  334.                 c1 = colors[2];   
  335.                 p = x / rectRight;   
  336.             }   
  337.             a = ave(Color.alpha(c0), Color.alpha(c1), p);   
  338.             r = ave(Color.red(c0), Color.red(c1), p);   
  339.             g = ave(Color.green(c0), Color.green(c1), p);   
  340.             b = ave(Color.blue(c0), Color.blue(c1), p);   
  341.             return Color.argb(a, r, g, b);   
  342.         }   
  343.            
  344.         private int ave(int s, int d, float p) {   
  345.             return s + Math.round(p * (d - s));   
  346.         }   
  347.     }   
  348.        
  349.     /**  
  350.      * 回调接口  
  351.      * @author <a href="clarkamx@gmail.com">LynK</a>  
  352.      *   
  353.      * Create on 2012-1-6 上午8:21:05  
  354.      *  
  355.      */  
  356.     public interface OnColorChangedListener {   
  357.         /**  
  358.          * 回调函数  
  359.          * @param color 选中的颜色  
  360.          */  
  361.         void colorChanged(int color);   
  362.     }   
  363.        
  364.     public String getTitle() {   
  365.         return title;   
  366.     }   
  367.   
  368.     public void setTitle(String title) {   
  369.         this.title = title;   
  370.     }   
  371.   
  372.     public int getmInitialColor() {   
  373.         return mInitialColor;   
  374.     }   
  375.   
  376.     public void setmInitialColor(int mInitialColor) {   
  377.         this.mInitialColor = mInitialColor;   
  378.     }   
  379.   
  380.     public OnColorChangedListener getmListener() {   
  381.         return mListener;   
  382.     }   
  383.   
  384.     public void setmListener(OnColorChangedListener mListener) {   
  385.         this.mListener = mListener;   
  386.     }   
  387. }  
  • 1
  • 2
  • 3
  • 下一页

相关内容