Android 颜色选择控件

这个View是API DEMO 里面ColorPickDialog一个对话框类里面抽取出来了一个类,本来在ColorPickViewDialog.java里面是一个内部类。


package com.aiscot.gesture.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.aiscot.gesture.R;
import com.aiscot.gesture.activity.GestureColorActivity;


public class ColorPickerView extends View {
	private Paint mPaint;
	private Paint mCenterPaint;
	private final int[] mColors;
	private OnColorChangedListener mListener;
	
	private boolean isSelected = false;
	
	
	public ColorPickerView(Context context) {
		super(context);
		mColors = new int[] { 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF,
				0xFF00FF00, 0xFFFFFF00, 0xFFFF0000 };
		Shader s = new SweepGradient(0, 0, mColors, null);
		
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setShader(s);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(STROKE_WIDTH);
		mPaint.setAntiAlias(true);
		mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mCenterPaint.setAntiAlias(true);
		mCenterPaint.setColor(Color.CYAN);
		mCenterPaint.setStrokeWidth(5);
	}

	public ColorPickerView(Context context,AttributeSet att){
		super(context,att);
		mColors = new int[] { 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF,
				0xFF00FF00, 0xFFFFFF00, 0xFFFF0000 };
		Shader s = new SweepGradient(0, 0, mColors, null);
		
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setShader(s);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(STROKE_WIDTH);
		mPaint.setAntiAlias(true);
		mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mCenterPaint.setAntiAlias(true);
		mCenterPaint.setColor(Color.CYAN);
		mCenterPaint.setStrokeWidth(5);
	}
	
	public ColorPickerView(Context context,AttributeSet att,int defStyle){
		super(context,att,defStyle);
		mColors = new int[] { 0xFFFF0000, 0xFFFF00FF, 0xFF0000FF, 0xFF00FFFF,
				0xFF00FF00, 0xFFFFFF00, 0xFFFF0000 };
		Shader s = new SweepGradient(0, 0, mColors, null);
		
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setShader(s);
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeWidth(STROKE_WIDTH);
		mPaint.setAntiAlias(true);
		
		mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mCenterPaint.setAntiAlias(true);
		mCenterPaint.setColor(Color.CYAN);
		mCenterPaint.setStrokeWidth(5);
	}
	
	
	/**
	 * 初始选中的颜色
	 * @param color
	 */
	public void setInitColor(int color){
		mCenterPaint.setColor(color);
	}
	
	
	public void setOnColorChangedListener(OnColorChangedListener listener){
		mListener = listener;
	}
	
	private boolean mTrackingCenter;
	private boolean mHighlightCenter;

	@Override
	protected void onDraw(Canvas canvas) {
		mPaint.setStrokeWidth(STROKE_WIDTH);
		float r = CENTER_X - mPaint.getStrokeWidth() * 0.5f;
		
		canvas.translate(CENTER_X, CENTER_X);
		canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
		canvas.drawCircle(0, 0, CENTER_RADIUS, mCenterPaint);
		Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.color_select);
		//是否绘制中间的对号
		if(isSelected)canvas.drawBitmap(bmp, -bmp.getWidth()/2, -bmp.getHeight()/2, new Paint());
		if (mTrackingCenter) {
			int c = mCenterPaint.getColor();
			mCenterPaint.setStyle(Paint.Style.STROKE);
			if (mHighlightCenter) {
				mCenterPaint.setAlpha(0xFF);
			} else {
				mCenterPaint.setAlpha(0x80);
			}
			canvas.drawCircle(0, 0,
					CENTER_RADIUS + mCenterPaint.getStrokeWidth(), mCenterPaint);
			mCenterPaint.setStyle(Paint.Style.FILL);
			mCenterPaint.setColor(c);
		}
	}

	
	


	public void setSelected(boolean isSelected) {
		
		this.isSelected = isSelected;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(CENTER_X * 2, CENTER_Y * 2);
	}
	
	
	//设置View的整个宽度,其他单位自动根据这个值调整
	public void setMaxWidth(int width){
		CENTER_X = width/2;
		CENTER_Y = width/2;
		CENTER_RADIUS = (int) (width/2.5/2);
		STROKE_WIDTH = (int) (width/2.3)-CENTER_RADIUS;
	}
	
	/**
	 * 整个View的宽度
	 */
	private static int CENTER_X = 100;
	/**
	 * 整个View的高度
	 */
	private static int CENTER_Y = 100;
	/**
	 * 中间圆的半径
	 */
	private static int CENTER_RADIUS = 50;
	/**
	 * 外圈圆的宽度
	 */
	private static int STROKE_WIDTH = 100;
	
	
	private int floatToByte(float x) {
		int n = java.lang.Math.round(x);
		return n;
	}

	private int pinToByte(int n) {
		if (n < 0) {
			n = 0;
		} else if (n > 255) {
			n = 255;
		}
		return n;
	}

	private int ave(int s, int d, float p) {
		return s + java.lang.Math.round(p * (d - s));
	}
	
	private int interpColor(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);
	}

	private int rotateColor(int color, float rad) {
		float deg = rad * 180 / 3.1415927f;
		int r = Color.red(color);
		int g = Color.green(color);
		int b = Color.blue(color);

		ColorMatrix cm = new ColorMatrix();
		ColorMatrix tmp = new ColorMatrix();

		cm.setRGB2YUV();
		tmp.setRotate(0, deg);
		cm.postConcat(tmp);
		tmp.setYUV2RGB();
		cm.postConcat(tmp);

		final float[] a = cm.getArray();

		int ir = floatToByte(a[0] * r + a[1] * g + a[2] * b);
		int ig = floatToByte(a[5] * r + a[6] * g + a[7] * b);
		int ib = floatToByte(a[10] * r + a[11] * g + a[12] * b);

		return Color.argb(Color.alpha(color), pinToByte(ir), pinToByte(ig),
				pinToByte(ib));
	}

	private static final float PI = 3.1415926f;

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float x = event.getX() - CENTER_X;
		float y = event.getY() - CENTER_Y;
		boolean inCenter = java.lang.Math.sqrt(x * x + y * y) <= CENTER_RADIUS;
		
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mTrackingCenter = inCenter;
			GestureColorActivity.mInstance.restureImg();
			setSelected(true);
			if (inCenter) {
				mHighlightCenter = true;
				invalidate();
				break;
			}
		case MotionEvent.ACTION_MOVE:
			if (mTrackingCenter) {
				if (mHighlightCenter != inCenter) {
					mHighlightCenter = inCenter;
					invalidate();
				}
			} else {
				float angle = (float) java.lang.Math.atan2(y, x);
				// need to turn angle [-PI ... PI] into unit [0....1]
				float unit = angle / (2 * PI);
				if (unit < 0) {
					unit += 1;
				}
				mCenterPaint.setColor(interpColor(mColors, unit));
				invalidate();
			}
			break;
		case MotionEvent.ACTION_UP:
			GestureColorActivity.mInstance.setViewColor(mCenterPaint.getColor());
			if (mTrackingCenter) {
				if (inCenter && mListener!= null) {
					mListener.colorChanged(mCenterPaint.getColor());
				}
				mTrackingCenter = false; // so we draw w/o halo
				invalidate();
			}
			break;
		}
		return true;
	}
	
	public interface OnColorChangedListener {
		void colorChanged(int color);
	}

}

在布局文件里添加ColorPickView

    <your_package.ColorPickerView
        android:id="@+id/colorpickerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/block"
        android:layout_centerHorizontal="true"
         />
至于怎么在Activity里使用就不必具体描述了,只要把setMaxWidth()设置一下就OK 我自己的设置的是屏幕宽度*0.87

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
功能很完善的颜色选择控件,不过,demo只是演示了如何在PreferenceActivity中ColorPickerPreference,其实完全可以在一般的布局中调用它的ColorPickerDialog类,这样适用范围更广一些。项目地址:https://github.com/attenzione/android-ColorPickerPreference 效果图:如何使用public class MainActivity extends Activity  implements ColorPickerDialog.OnColorChangedListener{ private Button chooseButton; private View preView;//预览视图 @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); this.setContentView(R.layout.main); preView = findViewById(R.id.preView); chooseButton = (Button) findViewById(R.id.chooseButton); chooseButton.setOnClickListener(new OnClickListener(){             @Override             public void onClick(View v){                 ColorPickerDialog mDialog = new ColorPickerDialog(MainActivity.this, 0xff333333);//弹出选择器对话框,并设置初始颜色                 mDialog.setOnColorChangedListener(MainActivity.this);  //设置监听器,监听颜色选择,需要实现onColorChanged方法                                                                                                                    mDialog.setAlphaSliderVisible(true);                 mDialog.setHexValueEnabled(true);                                                   mDialog.show();  //弹出选择器对话框                     }         }); } //实现ColorPickerDialog.OnColorChangedListener @Override public void onColorChanged(int color) { preView.setBackgroundColor(color); } }
要实现一个自定义控件来实现Android网格选择颜色,可以按照以下步骤进行: 1. 创建一个继承自View或其子类的自定义控件类,例如ColorGridView。 2. 在该类中添加必要的属性,例如颜色数组、列数等。 3. 重写onMeasure方法,计算控件的大小。 4. 重写onDraw方法,在控件内绘制颜色格子。 5. 处理触摸事件,当用户点击某个颜色格子时,将该格子的颜色作为选择结果返回。 6. (可选)添加其他交互功能,例如滑动、长按等。 以下是一个简单的实现示例: ``` public class ColorGridView extends View { private int[] colors; private int columnCount; private int selectedColor; public ColorGridView(Context context) { super(context); init(null, 0); } public ColorGridView(Context context, AttributeSet attrs) { super(context, attrs); init(attrs, 0); } public ColorGridView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(attrs, defStyle); } private void init(AttributeSet attrs, int defStyle) { // 初始化属性 TypedArray a = getContext().obtainStyledAttributes( attrs, R.styleable.ColorGridView, defStyle, 0); // 读取颜色数组 int colorsId = a.getResourceId(R.styleable.ColorGridView_colors, 0); if (colorsId != 0) { TypedArray colorsArray = getResources().obtainTypedArray(colorsId); colors = new int[colorsArray.length()]; for (int i = 0; i < colorsArray.length(); i++) { colors[i] = colorsArray.getColor(i, 0); } colorsArray.recycle(); } // 读取列数 columnCount = a.getInt(R.styleable.ColorGridView_columnCount, 4); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 计算控件大小 int width = MeasureSpec.getSize(widthMeasureSpec); int height = (colors.length / columnCount + 1) * width / columnCount; setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { // 绘制颜色格子 int width = getWidth() / columnCount; int height = width; Paint paint = new Paint(); for (int i = 0; i < colors.length; i++) { int x = (i % columnCount) * width; int y = (i / columnCount) * height; paint.setColor(colors[i]); canvas.drawRect(x, y, x + width, y + height, paint); } } @Override public boolean onTouchEvent(MotionEvent event) { // 处理触摸事件 if (event.getAction() == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); int index = (y / (getWidth() / columnCount)) * columnCount + x / (getWidth() / columnCount); if (index < colors.length) { selectedColor = colors[index]; invalidate(); return true; } } return super.onTouchEvent(event); } public int getSelectedColor() { return selectedColor; } } ``` 在布局文件中可以这样使用: ``` <com.example.ColorGridView android:id="@+id/color_grid_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:colors="@array/colors" app:columnCount="4" /> ``` 其中,colors和columnCount是自定义属性,可以在res/values/attrs.xml文件中定义: ``` <declare-styleable name="ColorGridView"> <attr name="colors" format="reference" /> <attr name="columnCount" format="integer" /> </declare-styleable> ``` 这样,就可以通过ColorGridView控件来实现Android网格选择颜色了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值