android 自定义View【2】对话框取色&色盘取色的实现
一、概述:通过该例子了解以下内容:
二、介绍运用api demo 中的ColorPickerDialog 步骤:实现对话框取色。
<span style="font-size:18px;">/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package demo.dim.getcolordemo; import android.os.Bundle; import android.app.Dialog; import android.content.Context; import android.graphics.*; import android.util.Log; import android.view.MotionEvent; import android.view.View; public class ColorPickerDialog extends Dialog { public interface OnColorChangedListener { void colorChanged(int color); } private OnColorChangedListener mListener; private int mInitialColor; private static class ColorPickerView extends View { private Paint mPaint; private Paint mCenterPaint; private final int[] mColors; private OnColorChangedListener mListener; private String TAG="ColorPicker-->>"; ColorPickerView(Context c, OnColorChangedListener l, int color) { super(c); mListener = l; 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(32); mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCenterPaint.setColor(color); mCenterPaint.setStrokeWidth(5); } private boolean mTrackingCenter; private boolean mHighlightCenter; @Override protected void onDraw(Canvas canvas) { 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); 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); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //只有在 0 0 200 200 范围内。定义视图大小。 //就是200*200的正方形范围内。 setMeasuredDimension(CENTER_X*2, CENTER_Y*2); } private static final int CENTER_X = 100; private static final int CENTER_Y = 100; private static final int CENTER_RADIUS = 32; 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]; /** * 四舍五入 * private int ave(int s, int d, float p) { return s + java.lang.Math.round(p * (d - s)); } */ 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) { //setMeasuredDimension(CENTER_X*2, CENTER_Y*2); //这决定了 event.getX() <=200;event.getY()<=200 float x = event.getX() - CENTER_X; float y = event.getY() - CENTER_Y; Log.i(TAG, "x="+ event.getX()+" y="+event.getY()); //如果半径小于等于32 则认为是中心区域。 // java.lang.Math.sqrt(x*x + y*y) 勾股定理 算半径。 boolean inCenter = java.lang.Math.sqrt(x*x + y*y) <= CENTER_RADIUS; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTrackingCenter = inCenter; //按下动作触发时,如果点击的是中心,则高亮中间部分。 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] //将角度 转换为【0,1】区间的值。如果为负数则加1,。 float unit = angle/(2*PI); if (unit < 0) { unit += 1; } //取色的关键部位 mCenterPaint.setColor(interpColor(mColors, unit)); invalidate(); } break; case MotionEvent.ACTION_UP: //监听松手动作时,如果是从中心部位松手,则取消对话框。否则中心标志位置false //然后重新绘图。 if (mTrackingCenter) { if (inCenter) { mListener.colorChanged(mCenterPaint.getColor()); } mTrackingCenter = false; // so we draw w/o halo invalidate(); } break; } return true; } } /** * * @param context :always is the context of activity * @param listener: the OnColorChangedListener listen the change of color * @param initialColor: initial the color of the ColorPickerDialog */ public ColorPickerDialog(Context context, OnColorChangedListener listener, int initialColor) { super(context); mListener = listener; mInitialColor = initialColor; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //dismiss the dialog if the color is selected. //对话框取色中间被点击时,监听到颜色已经选定,则消失对话框。 OnColorChangedListener l = new OnColorChangedListener() { public void colorChanged(int color) { mListener.colorChanged(color); dismiss(); } }; //set the colorPickerView to the content view of dialog setContentView(new ColorPickerView(getContext(), l, mInitialColor)); //set title of dialog setTitle("Pick a Color"); } } </span>
3、在布局文件activity_main.xml中添加一个button 代码如下:
<span style="font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/btnGetColorDia" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:textSize="20dp" android:text="对话框方式获取颜色" /> </RelativeLayout></span>
<span style="font-size:18px;">package demo.dim.getcolordemo; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import demo.dim.getcolordemo.ColorPickerDialog.OnColorChangedListener; public class MainActivity extends Activity { private final static String TAG="GET COLOR DEMO-->>"; private ColorPickerDialog ColorPicker=null; private Button btnGetColorDia=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnGetColorDia=(Button)findViewById(R.id.btnGetColorDia); btnGetColorDia.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub ColorPicker.show(); } }); <strong> ColorPicker=new ColorPickerDialog(this, new OnColorChangedListener() { @Override public void colorChanged(int color) { // TODO Auto-generated method stub btnGetColorDia.setBackgroundColor(color); } }, Color.BLUE);</strong> } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } } </span>
先看看运行效果:
三、介绍色盘取色步骤:
<span style="font-size:18px;">package demo.dim.getcolordemo; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; public class ColorPickerView extends View{ private String TAG="colorPicker"; private boolean DBG=false; private Context mContext; private Paint mRightPaint; //画笔 private int mHeight; //view高 private int mWidth; //view宽 private int[] mRightColors; private int LEFT_WIDTH; private Bitmap mLeftBitmap; private Bitmap mLeftBitmap2; private Paint mBitmapPaint; private PointF mLeftSelectPoint; private OnColorChangedListenerD mChangedListenerD; private boolean mLeftMove = false; private float mLeftBitmapRadius; private Bitmap mGradualChangeBitmap; private Bitmap bitmapTemp; private int mCallBackColor = Integer.MAX_VALUE; int newWidgth; int newHeigh; public static String hexColor="FFFFFF"; public static int ColorText=0; private Canvas mCan=null; public ColorPickerView(Context context) { this(context, null); } public ColorPickerView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; init(); } public void setOnColorChangedListennerD(OnColorChangedListenerD listener) { mChangedListenerD = listener; } private void init() { bitmapTemp = BitmapFactory.decodeResource(getResources(), R.drawable.piccolor); mRightPaint = new Paint(); mRightPaint.setStyle(Paint.Style.FILL); mRightPaint.setStrokeWidth(1); mRightColors = new int[3]; mRightColors[0] = Color.WHITE; mRightColors[2] = Color.BLACK; mBitmapPaint = new Paint(); mLeftBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.reading__color_view__button); mLeftBitmap2 = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.reading__color_view__button_press); mLeftBitmapRadius = mLeftBitmap.getWidth() / 2; mLeftSelectPoint = new PointF(0, 0); newWidgth=BitmapFactory.decodeResource(getResources(), R.drawable.piccolor).getWidth(); newHeigh=BitmapFactory.decodeResource(getResources(), R.drawable.piccolor).getHeight(); } //important patient please!!! @Override protected void onDraw(Canvas canvas) { //mCan=canvas; canvas.drawBitmap(getGradual() , null , new Rect(0, 0, LEFT_WIDTH , mHeight ), mBitmapPaint); if(!hexColor.equals("ffffff")) { System.out.println(TAG+"draw2"); if (mLeftMove) { canvas.drawBitmap(mLeftBitmap, mLeftSelectPoint.x - mLeftBitmapRadius, mLeftSelectPoint.y - mLeftBitmapRadius, mBitmapPaint); } else { try { canvas.drawBitmap(mLeftBitmap2, mLeftSelectPoint.x - mLeftBitmapRadius, mLeftSelectPoint.y - mLeftBitmapRadius, mBitmapPaint); } catch (Exception e) { // TODO: handle exception } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { mWidth = width; } else { mWidth = newHeigh; } if (heightMode == MeasureSpec.EXACTLY) { mHeight = height; } else { mHeight = newHeigh; } LEFT_WIDTH = mWidth; setMeasuredDimension(mWidth, mHeight); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: ColorText=getLeftColor(x, y); // System.out.println("color num="+getLeftColor(x, y)); if(getLeftColor(x, y)!=-1) invalidate(); case MotionEvent.ACTION_MOVE: { try { // mLeftMove = true; if(getLeftColor(x, y)!=-1) { ColorText=getLeftColor(x, y); proofLeft(x, y); int rmove = Color.red(ColorText); int gmove = Color.green(ColorText); int bmove = Color.blue(ColorText); //System.out.println("color rgb"); String r11=Integer.toHexString(rmove); String g11=Integer.toHexString(gmove); String b11=Integer.toHexString(bmove); String colorStr1=r11+g11+b11; //十六进制的颜色字符串。 //System.out.println("color="+colorStr1); hexColor=colorStr1; mChangedListenerD.onColorChanged(ColorText, colorStr1); //changeBGLIS.onColorChanged(ColorText); invalidate(); } } catch (Exception e) { // TODO: handle exception //invalidate(); } } break; case MotionEvent.ACTION_UP: try { if(getLeftColor(x, y)!=-1) { ColorText=getLeftColor(x, y); //System.out.println("color="+ColorText); mLeftMove = false; int rup = Color.red(ColorText); int gup= Color.green(ColorText); int bup = Color.blue(ColorText); //System.out.println("color rgb"); String rupStr=Integer.toHexString(rup); String gupStr=Integer.toHexString(gup); String bupStr=Integer.toHexString(bup); String colorUpStr=rupStr+gupStr+bupStr; //十六进制的颜色字符串。 System.out.println("color="+colorUpStr); hexColor=colorUpStr; mChangedListenerD.onColorChanged(ColorText, colorUpStr); invalidate(); } } catch (Exception e) { // TODO: handle exception // invalidate(); } } return true; } @Override protected void onDetachedFromWindow() { if (mGradualChangeBitmap != null && mGradualChangeBitmap.isRecycled() == false) { mGradualChangeBitmap.recycle(); } if (mLeftBitmap != null && mLeftBitmap.isRecycled() == false) { mLeftBitmap.recycle(); } if (mLeftBitmap2 != null && mLeftBitmap2.isRecycled() == false) { mLeftBitmap2.recycle(); } super.onDetachedFromWindow(); } private Bitmap getGradual() { if (mGradualChangeBitmap == null) { Paint leftPaint = new Paint(); leftPaint.setStrokeWidth(1); mGradualChangeBitmap = Bitmap.createBitmap(LEFT_WIDTH, mHeight, Config.RGB_565); mGradualChangeBitmap.eraseColor(Color.WHITE); Canvas canvas = new Canvas(mGradualChangeBitmap); canvas.drawBitmap( bitmapTemp, null , new Rect(0, 0, LEFT_WIDTH , mHeight ), mBitmapPaint); } return mGradualChangeBitmap; } // 校正xy private void proofLeft(float x, float y) { if (x < 0) { mLeftSelectPoint.x = 0; } else if (x > (LEFT_WIDTH)) { mLeftSelectPoint.x = LEFT_WIDTH; } else { mLeftSelectPoint.x = x; } if (y < 0) { mLeftSelectPoint.y = 0; } else if (y > (mHeight - 0)) { mLeftSelectPoint.y = mHeight - 0; } else { mLeftSelectPoint.y = y; } } private int getLeftColor(float x, float y) { Bitmap temp = getGradual(); // 为了防止越界 int intX = (int) x; int intY = (int) y; if(intX<0)intX=0; if(intY<0)intY=0; if (intX >= temp.getWidth()) { intX = temp.getWidth() - 1; } if (intY >= temp.getHeight()) { intY = temp.getHeight() - 1; } System.out.println("leftColor"+temp.getPixel(intX, intY)); return temp.getPixel(intX, intY); } // ### 内部类 ### public interface OnColorChangedListenerD { void onColorChanged(int color, String hexStrColor); } } </span>
2、在布局文件activity_main.xml中添加一个button 并添加ColorPickerView 代码如下:
<span style="font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/btnGetColorDia" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:textSize="20dp" android:text="对话框方式获取颜色" /> <strong> <Button android:id="@+id/btnColorDisk" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/btnGetColorDia" android:text="从色盘吸管获取颜色" /> <demo.dim.getcolordemo.ColorPickerView android:id="@+id/colorPickerDisk" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/btnColorDisk" android:layout_alignParentTop="true" android:layout_marginTop="150dp" android:visibility="invisible" /></strong> </RelativeLayout></span>
3、修改MainActivity中代码如下:
<span style="font-size:18px;">package demo.dim.getcolordemo; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import demo.dim.getcolordemo.ColorPickerDialog.OnColorChangedListener; import demo.dim.getcolordemo.ColorPickerView .OnColorChangedListenerD; public class MainActivity extends Activity { /** * Tag of this class, more clear and convenient when you debugging */ private final static String TAG="GET COLOR DEMO-->>"; /** * the object of the ColorPickerDialog */ private ColorPickerDialog ColorPicker=null; /** * btnGetColorDia use to trigger the dialog of color when the button is click */ private Button btnGetColorDia=null; <span style="color:#ff6666;"> /** * color Disk */ ColorPickerView colorPickerDisk=null; /** * button of colorDisk */ Button btnColorDisk=null;</span> /** * */ int intChange=1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); <span style="color:#ff6666;"> colorPickerDisk=new ColorPickerView(this); //find the ID of View colorPickerDisk=(ColorPickerView)findViewById(R.id.colorPickerDisk); btnColorDisk=(Button)findViewById(R.id.btnColorDisk);</span> btnGetColorDia=(Button)findViewById(R.id.btnGetColorDia); btnGetColorDia.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub ColorPicker.show(); } }); <span style="color:#ff6666;">//how to use ColorPickerDialog Class ,the default color is blue ,here is Color.BLUE ColorPicker=new ColorPickerDialog(this, new OnColorChangedListener() { @Override public void colorChanged(int color) { // TODO Auto-generated method stub //change the background of button when the color is changed . btnGetColorDia.setBackgroundColor(color); } }, Color.BLUE); colorPickerDisk.setOnColorChangedListennerD(new OnColorChangedListenerD() { @Override public void onColorChanged(int color, String hexStrColor) { // TODO Auto-generated method stub btnColorDisk.setBackgroundColor(color); btnColorDisk.setText("Color is "+hexStrColor); } }); btnColorDisk.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if(intChange%2==0) { colorPickerDisk.setVisibility(View.INVISIBLE); }else { colorPickerDisk.setVisibility(View.VISIBLE); } intChange++; } }); }</span> @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } } </span>
效果图如下:
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。