`
iaiai
  • 浏览: 2204687 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android 颜色选择器(ColorPicker)

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

先上图
1.测试界面

2. 调色板对话框

3. 选择颜色

4.改变字体颜色


调色板对话框
ColorPickerDialog.java
package com.dwood.paintdemo;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

public class ColorPickerDialog extends Dialog {
	private final boolean debug = true;
	private final String TAG = "ColorPicker";
	
	Context context;
	private String title;//标题
	private int mInitialColor;//初始颜色
    private OnColorChangedListener mListener;

	/**
     * 初始颜色黑色
     * @param context
     * @param title 对话框标题
     * @param listener 回调
     */
    public ColorPickerDialog(Context context, String title, 
    		OnColorChangedListener listener) {
    	this(context, Color.BLACK, title, listener);
    }
    
    /**
     * 
     * @param context
     * @param initialColor 初始颜色
     * @param title 标题
     * @param listener 回调
     */
    public ColorPickerDialog(Context context, int initialColor, 
    		String title, OnColorChangedListener listener) {
        super(context);
        this.context = context;
        mListener = listener;
        mInitialColor = initialColor;
        this.title = title;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WindowManager manager = getWindow().getWindowManager();
		int height = (int) (manager.getDefaultDisplay().getHeight() * 0.5f);
		int width = (int) (manager.getDefaultDisplay().getWidth() * 0.7f);
		ColorPickerView myView = new ColorPickerView(context, height, width);
        setContentView(myView);
        setTitle(title);
    }
    
    private class ColorPickerView extends View {
    	private Paint mPaint;//渐变色环画笔
    	private Paint mCenterPaint;//中间圆画笔
    	private Paint mLinePaint;//分隔线画笔
    	private Paint mRectPaint;//渐变方块画笔
    	
    	private Shader rectShader;//渐变方块渐变图像
    	private float rectLeft;//渐变方块左x坐标
    	private float rectTop;//渐变方块右x坐标
    	private float rectRight;//渐变方块上y坐标
    	private float rectBottom;//渐变方块下y坐标
        
    	private final int[] mCircleColors;//渐变色环颜色
    	private final int[] mRectColors;//渐变方块颜色
    	
    	private int mHeight;//View高
    	private int mWidth;//View宽
    	private float r;//色环半径(paint中部)
    	private float centerRadius;//中心圆半径
    	
    	private boolean downInCircle = true;//按在渐变环上
    	private boolean downInRect;//按在渐变方块上
    	private boolean highlightCenter;//高亮
    	private boolean highlightCenterLittle;//微亮
    	
		public ColorPickerView(Context context, int height, int width) {
			super(context);
			this.mHeight = height - 36;
			this.mWidth = width;
			setMinimumHeight(height - 36);
			setMinimumWidth(width);
			
			//渐变色环参数
	    	mCircleColors = new int[] {0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 
	    			0xFF00FFFF, 0xFF00FF00,0xFFFFFF00, 0xFFFF0000};
	    	Shader s = new SweepGradient(0, 0, mCircleColors, null);
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setShader(s);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(50);
            r = width / 2 * 0.7f - mPaint.getStrokeWidth() * 0.5f;
            
            //中心圆参数
            mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mCenterPaint.setColor(mInitialColor);
            mCenterPaint.setStrokeWidth(5);
            centerRadius = (r - mPaint.getStrokeWidth() / 2 ) * 0.7f;
            
            //边框参数
            mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mLinePaint.setColor(Color.parseColor("#72A1D1"));
            mLinePaint.setStrokeWidth(4);
            
            //黑白渐变参数
            mRectColors = new int[]{0xFF000000, mCenterPaint.getColor(), 0xFFFFFFFF};
            mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mRectPaint.setStrokeWidth(5);
            rectLeft = -r - mPaint.getStrokeWidth() * 0.5f;
            rectTop = r + mPaint.getStrokeWidth() * 0.5f + 
            		mLinePaint.getStrokeMiter() * 0.5f + 15;
            rectRight = r + mPaint.getStrokeWidth() * 0.5f;
            rectBottom = rectTop + 50;
		}

		@Override
		protected void onDraw(Canvas canvas) {
			//移动中心
            canvas.translate(mWidth / 2, mHeight / 2 - 50);
            //画中心圆
            canvas.drawCircle(0, 0, centerRadius,  mCenterPaint);
            //是否显示中心圆外的小圆环
            if (highlightCenter || highlightCenterLittle) {
                int c = mCenterPaint.getColor();
                mCenterPaint.setStyle(Paint.Style.STROKE);
                if(highlightCenter) {
                	mCenterPaint.setAlpha(0xFF);
                }else if(highlightCenterLittle) {
                	mCenterPaint.setAlpha(0x90);
                }
                canvas.drawCircle(0, 0, 
                		centerRadius + mCenterPaint.getStrokeWidth(),  mCenterPaint);
                
                mCenterPaint.setStyle(Paint.Style.FILL);
                mCenterPaint.setColor(c);
            }
            //画色环
            canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
            //画黑白渐变块
            if(downInCircle) {
            	mRectColors[1] = mCenterPaint.getColor();
            }
            rectShader = new LinearGradient(rectLeft, 0, rectRight, 0, mRectColors, null, Shader.TileMode.MIRROR);
            mRectPaint.setShader(rectShader);
            canvas.drawRect(rectLeft, rectTop, rectRight, rectBottom, mRectPaint);
            float offset = mLinePaint.getStrokeWidth() / 2;
            canvas.drawLine(rectLeft - offset, rectTop - offset * 2, 
            		rectLeft - offset, rectBottom + offset * 2, mLinePaint);//左
            canvas.drawLine(rectLeft - offset * 2, rectTop - offset, 
            		rectRight + offset * 2, rectTop - offset, mLinePaint);//上
            canvas.drawLine(rectRight + offset, rectTop - offset * 2, 
            		rectRight + offset, rectBottom + offset * 2, mLinePaint);//右
            canvas.drawLine(rectLeft - offset * 2, rectBottom + offset, 
            		rectRight + offset * 2, rectBottom + offset, mLinePaint);//下
			super.onDraw(canvas);
		}
		
		@Override
		public boolean onTouchEvent(MotionEvent event) {
			float x = event.getX() - mWidth / 2;
            float y = event.getY() - mHeight / 2 + 50;
            boolean inCircle = inColorCircle(x, y, 
            		r + mPaint.getStrokeWidth() / 2, r - mPaint.getStrokeWidth() / 2);
            boolean inCenter = inCenter(x, y, centerRadius);
            boolean inRect = inRect(x, y);
            
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                	downInCircle = inCircle;
                	downInRect = inRect;
                	highlightCenter = inCenter;
                case MotionEvent.ACTION_MOVE:
                	if(downInCircle && inCircle) {//down按在渐变色环内, 且move也在渐变色环内
                		float angle = (float) Math.atan2(y, x);
                        float unit = (float) (angle / (2 * Math.PI));
                        if (unit < 0) {
                            unit += 1;
                        }
	               		mCenterPaint.setColor(interpCircleColor(mCircleColors, unit));
	               		if(debug) Log.v(TAG, "色环内, 坐标: " + x + "," + y);
                	}else if(downInRect && inRect) {//down在渐变方块内, 且move也在渐变方块内
                		mCenterPaint.setColor(interpRectColor(mRectColors, x));
                	}
                	if(debug) Log.v(TAG, "[MOVE] 高亮: " + highlightCenter + "微亮: " + highlightCenterLittle + " 中心: " + inCenter);
                	if((highlightCenter && inCenter) || (highlightCenterLittle && inCenter)) {//点击中心圆, 当前移动在中心圆
                		highlightCenter = true;
                		highlightCenterLittle = false;
                	} else if(highlightCenter || highlightCenterLittle) {//点击在中心圆, 当前移出中心圆
                		highlightCenter = false;
                		highlightCenterLittle = true;
                	} else {
                		highlightCenter = false;
                		highlightCenterLittle = false;
                	}
                   	invalidate();
                	break;
                case MotionEvent.ACTION_UP:
                	if(highlightCenter && inCenter) {//点击在中心圆, 且当前启动在中心圆
                		if(mListener != null) {
                			mListener.colorChanged(mCenterPaint.getColor());
                    		ColorPickerDialog.this.dismiss();
                		}
                	}
                	if(downInCircle) {
                		downInCircle = false;
                	}
                	if(downInRect) {
                		downInRect = false;
                	}
                	if(highlightCenter) {
                		highlightCenter = false;
                	}
                	if(highlightCenterLittle) {
                		highlightCenterLittle = false;
                	}
                	invalidate();
                    break;
            }
            return true;
		}

		@Override
		protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
			super.onMeasure(mWidth, mHeight);
		}

		/**
		 * 坐标是否在色环上
		 * @param x 坐标
		 * @param y 坐标
		 * @param outRadius 色环外半径
		 * @param inRadius 色环内半径
		 * @return
		 */
		private boolean inColorCircle(float x, float y, float outRadius, float inRadius) {
			double outCircle = Math.PI * outRadius * outRadius;
			double inCircle = Math.PI * inRadius * inRadius;
			double fingerCircle = Math.PI * (x * x + y * y);
			if(fingerCircle < outCircle && fingerCircle > inCircle) {
				return true;
			}else {
				return false;
			}
		}
		
		/**
		 * 坐标是否在中心圆上
		 * @param x 坐标
		 * @param y 坐标
		 * @param centerRadius 圆半径
		 * @return
		 */
		private boolean inCenter(float x, float y, float centerRadius) {
			double centerCircle = Math.PI * centerRadius * centerRadius;
			double fingerCircle = Math.PI * (x * x + y * y);
			if(fingerCircle < centerCircle) {
				return true;
			}else {
				return false;
			}
		}
		
		/**
		 * 坐标是否在渐变色中
		 * @param x
		 * @param y
		 * @return
		 */
		private boolean inRect(float x, float y) {
			if( x <= rectRight && x >=rectLeft && y <= rectBottom && y >=rectTop) {
				return true;
			} else {
				return false;
			}
		}
		
		/**
		 * 获取圆环上颜色
		 * @param colors
		 * @param unit
		 * @return
		 */
		private int interpCircleColor(int colors[], float unit) {
            if (unit <= 0) {
                return colors[0];
            }
            if (unit >= 1) {
                return colors[colors.length - 1];
            }
            
            float p = unit * (colors.length - 1);
            int i = (int)p;
            p -= i;

            // now p is just the fractional part [0...1) and i is the index
            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);
        }
		
		/**
		 * 获取渐变块上颜色
		 * @param colors
		 * @param x
		 * @return
		 */
		private int interpRectColor(int colors[], float x) {
			int a, r, g, b, c0, c1;
        	float p;
        	if (x < 0) {
        		c0 = colors[0]; 
        		c1 = colors[1];
        		p = (x + rectRight) / rectRight;
        	} else {
        		c0 = colors[1];
        		c1 = colors[2];
        		p = x / rectRight;
        	}
        	a = ave(Color.alpha(c0), Color.alpha(c1), p);
        	r = ave(Color.red(c0), Color.red(c1), p);
        	g = ave(Color.green(c0), Color.green(c1), p);
        	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));
        }
    }
    
    /**
     * 回调接口
     * @author <a href="clarkamx@gmail.com">LynK</a>
     * 
     * Create on 2012-1-6 上午8:21:05
     *
     */
    public interface OnColorChangedListener {
    	/**
    	 * 回调函数
    	 * @param color 选中的颜色
    	 */
        void colorChanged(int color);
    }
    
    public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public int getmInitialColor() {
		return mInitialColor;
	}

	public void setmInitialColor(int mInitialColor) {
		this.mInitialColor = mInitialColor;
	}

	public OnColorChangedListener getmListener() {
		return mListener;
	}

	public void setmListener(OnColorChangedListener mListener) {
		this.mListener = mListener;
	}
}

测试界面
PaintDemoActivity.java
package com.dwood.paintdemo;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class PaintDemoActivity extends Activity {
    Context context;
    private Button btnColorPicker;
    private TextView tvText;
    
    private ColorPickerDialog dialog;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	context = this;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initViews();
    }
    /**
     * 初始化UI
     */
    private void initViews() {
    	btnColorPicker = (Button) findViewById(R.id.btn_color_picker);
    	btnColorPicker.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				dialog = new ColorPickerDialog(context, tvText.getTextColors().getDefaultColor(), 
						getResources().getString(R.string.btn_color_picker), 
						new ColorPickerDialog.OnColorChangedListener() {
					
					@Override
					public void colorChanged(int color) {
						tvText.setTextColor(color);
					}
				});
				dialog.show();
			}
		});
    	tvText = (TextView) findViewById(R.id.tv_text);
    }
}
  • 大小: 27.7 KB
  • 大小: 53.9 KB
  • 大小: 57.1 KB
  • 大小: 27.7 KB
分享到:
评论
1 楼 herrice 2013-07-05  
谢谢分享这么好的资源

相关推荐

    完美的android颜色选择器

    一个完善的Android颜色选择器应该具备多种功能,如选择颜色区域、调整色调、设置透明度等,以满足用户对颜色的精细化需求。在本项目“完美的android颜色选择器”中,我们将探讨其核心特点以及实现方法。 首先,颜色...

    android 颜色选择器

    本篇文章将深入探讨Android颜色选择器的实现原理、使用方法以及如何在项目中自定义和集成。 首先,Android SDK提供了一个内置的颜色选择器组件,名为`ColorPickerDialog`,但这通常只适用于简单的颜色选择需求。要...

    颜色选择对话框(ColorPicker)

    - 实现颜色选择器:使用`SeekBar`或触摸事件处理颜色选择。 - 处理颜色变化:监听颜色选择事件,更新颜色值,并可能触发其他操作,如设置背景色。 - 显示对话框:创建`AlertDialog`实例,设置自定义布局,并添加...

    Android 颜色选择器

    本篇文章将深入探讨Android颜色选择器的实现、使用方法以及相关API。 一、颜色选择器的基本概念 颜色选择器通常由一个主色盘和一个可选的颜色值指示器组成。用户可以在色盘上选择一种颜色,指示器会跟随移动并显示...

    Android颜色选择器源码

    本篇文章将深入探讨Android颜色选择器的源码,了解其工作原理以及如何自定义和集成到项目中。 颜色选择器的基本结构通常包括以下几个部分: 1. **颜色面板**:展示预设颜色的区域,可以是彩虹条、色块矩阵或者...

    android颜色选择器

    这个"android颜色选择器"的Demo旨在提供一个基础框架,帮助开发者理解如何实现这样的功能,尽管它可能并不完美,但可以作为一个起点,供有兴趣的开发者进行改进和优化。 颜色选择器通常包括一个色盘,用户可以通过...

    Android-Multi-ColorPicker这是最标准和最强大的多色选择器库

    6. **可定制化**:开发者可以根据自己的需求调整颜色选择器的外观和行为,如颜色网格的大小、滑块的样式等。 **集成与使用** 要将Android-Multi-ColorPicker集成到你的项目中,首先需要在你的`build.gradle`文件中...

    Android应用源码之颜色选择器.zip

    如果不希望从头开始编写颜色选择器,可以使用开源库,如“android-widget-colorpicker”或“android-color-picker”。这些库提供了现成的实现,只需简单集成即可在项目中使用。 8. **颜色选择器在应用中的应用场景...

    android 颜色选择器及弧形刻度盘

    - 在Android中,通常使用`ColorPicker`类来创建颜色选择器,但系统提供的`ColorPicker`功能有限。自定义颜色选择器通常需要从头构建,包括颜色滑块、色轮或者色谱等元素。 - 用户可以通过滑动选择RGB、HSV或HSL...

    Android颜色选择器HoloColorPicker.zip

    Android Holo ColorPicker是一个专为Android平台设计的开源颜色选择器组件,其设计风格遵循了Android的Holo主题。这个组件使得用户可以在应用程序中轻松选择颜色,提供了类似于原生Android系统的色彩选取体验。Holo...

    android 字体颜色选择器(ColorPicker)介绍

    在Android开发中,UI设计是至关重要的一环,而字体颜色选择器(ColorPicker)则为用户提供了一种方便的方式来选择和设置文字的颜色。本文将深入探讨Android中的ColorPicker组件及其使用方法。 首先,ColorPicker是一...

    ColorPicker-Android:一个简单的安卓颜色选择器

    【ColorPicker-Android】是一个专为安卓平台设计的简单易用的颜色选择器库。这个库由Uucky和Mariotaku在2015年创建,旨在为开发者提供一个直观、高效的用户界面,允许用户在应用中选取所需的颜色。在本文中,我们将...

    SimpleDroidColorPicker:简单的 Android 颜色选择器库

    SimpleDroidColorPicker是一个简单易用的 Android 颜色选择器库。 目前它处于预发布状态,支持环形、圆形和线性颜色选择器。 当前版本v0.3支持: 环形颜色选择器,圆形颜色选择器,三个线性颜色选择器 HSV线性...

    android 开发的色彩选择器

    本篇文章将详细探讨如何在Android中实现一个功能完备的颜色选择器,并涵盖其相关知识点。 首先,我们从基础开始。Android SDK提供了`ColorDrawable`和`ColorStateList`类来处理颜色。`ColorDrawable`用于显示单一...

    Android颜色自定义选择版

    2. **自定义View**:需要创建自定义的View或Widget来显示色板和颜色选择器。这可能涉及到对触控事件的处理,以及绘制颜色块和滑动条。 3. **颜色选择交互**:设计友好的用户交互,比如通过触摸滑动选择颜色,或者...

    Android应用源码之颜色选择器-IT计算机-毕业设计.zip

    首先,我们需要了解Android颜色选择器的基本构成。在Android中,颜色选择器通常由`ColorPicker`控件或者自定义视图实现。在`ColorPicker`中,用户可以通过滑动条选择红、绿、蓝(RGB)或色调、饱和度、亮度(HSV)值...

    colorpicker:一个简单的Android颜色选择器库

    颜色选择器一个简单的Android颜色选择器库下载下载或通过Gradle获取: implementation ' petrov.kristiyan:colorpicker-library:1.1.10 '如何使用范例1: ColorPicker colorPicker = new ColorPicker (activity);...

    Android获取RGB颜色 Android色盘选择

    当集成颜色选择器功能时,Android提供了一些库,如`colorpicker-master`可能就是一个实现色盘选择的库。这类库通常包含一个可交互的色盘视图,用户可以通过滑动或点击选择颜色,然后返回所选颜色的RGB值。例如,你...

Global site tag (gtag.js) - Google Analytics