现在的位置: 首页 > 综合 > 正文

Android 颜色选择器(ColorPicker)

2013年08月08日 ⁄ 综合 ⁄ 共 23324字 ⁄ 字号 评论关闭

 

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

 

先上图

1.测试界面

 

2.
调色板对话框

 

3. 选择颜色

 

4.改变字体颜色

 

 


调色板对话框

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. }  

 

测试界面 

PaintDemoActivity.java

Java代码 复制代码 收藏代码
  1. package com.dwood.paintdemo;   
  2.   
  3. import android.app.Activity;   
  4. import android.content.Context;   
  5. import android.os.Bundle;   
  6. import android.view.View;   
  7. import android.widget.Button;   
  8. import android.widget.TextView;   
  9.   
  10. public class PaintDemoActivity extends Activity {   
  11.     Context context;   
  12.     private Button btnColorPicker;   
  13.     private TextView tvText;   
  14.        
  15.     private

抱歉!评论已关闭.