android 自定义View【2】对话框取色&色盘取色的实现
来源:互联网 发布:企业建站优化方案 编辑:程序博客网 时间:2024/05/16 09:43
android 自定义View【2】对话框取色&色盘取色的实现
上一篇文章基本介绍了android自定义view的流程:继承view,复写view的一些方法。实现简单的自定义view。这篇文章主要介绍的是系统对话框取色功能,然后顺便介绍升级版,色盘取色【类似于ps中的吸管,对图片点击相应位置,获取那个位置的颜色】。
一、概述:通过该例子了解以下内容:
1、进一步了解android 自定义view。
2、知道如何获取图片上的颜色值。
3、监听屏幕touch,实现移动的时候自动取色。【onDraw与onMeasure 的配合】
4、了解定义接口和匿名内部类调用。
二、介绍运用api demo 中的ColorPickerDialog 步骤:实现对话框取色。
1、新建安卓工程、命名为GetColorDemo
2、将\android-sdks\samples\android-13\ApiDemos\src\com\example\android\apis\graphics目录下的 ColorPickerDialog.java 文件 拷贝到工程。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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btnGetColorDia=(Button)findViewById(R.id.btnGetColorDia);btnGetColorDia.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubColorPicker.show();}});<strong>ColorPicker=new ColorPickerDialog(this, new OnColorChangedListener() {@Overridepublic void colorChanged(int color) {// TODO Auto-generated method stubbtnGetColorDia.setBackgroundColor(color);}}, Color.BLUE);</strong>}@Overridepublic 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>
先看看运行效果:
三、介绍色盘取色步骤:
1、在以上工程基础上,增加一个类。这里命名为:ColorPickerView
代码如下:
<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!!!@Overrideprotected 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}} }}@Overrideprotected 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);}@Overridepublic 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;}@Overrideprotected 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;}// 校正xyprivate 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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);<span style="color:#ff6666;">colorPickerDisk=new ColorPickerView(this);//find the ID of ViewcolorPickerDisk=(ColorPickerView)findViewById(R.id.colorPickerDisk); btnColorDisk=(Button)findViewById(R.id.btnColorDisk);</span>btnGetColorDia=(Button)findViewById(R.id.btnGetColorDia);btnGetColorDia.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubColorPicker.show();}});<span style="color:#ff6666;">//how to use ColorPickerDialog Class ,the default color is blue ,here is Color.BLUEColorPicker=new ColorPickerDialog(this, new OnColorChangedListener() {@Overridepublic 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() {@Overridepublic void onColorChanged(int color, String hexStrColor) {// TODO Auto-generated method stubbtnColorDisk.setBackgroundColor(color);btnColorDisk.setText("Color is "+hexStrColor);}}); btnColorDisk.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub if(intChange%2==0) { colorPickerDisk.setVisibility(View.INVISIBLE); }else { colorPickerDisk.setVisibility(View.VISIBLE); } intChange++;}});}</span>@Overridepublic 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>
效果图如下:
RGB 查询工具网址: http://rgb.phpddt.com/
希望这篇小文章,对有需要的人有所帮助。
如有有问题!互相讨论!共同进步!
源码请点击这里。或加群:383012091 讨论。
0 0
- android 自定义View【2】对话框取色&色盘取色的实现
- Android自定义对话框的实现
- 自定义对话框的实现--Android
- Android自定义View的实现
- Android自定义View的实现
- android自定义view的实现
- Android 自定义view的实现
- android自定义View的实现
- Android自定义View的实现
- Android实现自定义对话框
- Android自定义View的属性,attr format取值类型
- 完全自定义Android对话框AlertDialog的实现
- android自定义实现好看的对话框
- android的自定义dialog对话框实现
- 完全自定义Android对话框AlertDialog的实现
- [Android]Android自定义View的实现
- Android自定义View实现
- Android 实现自定义View
- ajax同步、异步执行简单理解与证明
- NYOJ 60、75、113
- 最短路径算法学习
- 第十四周项目6-阅读程序
- MFC 处理 HTTP 请求的基本方法
- android 自定义View【2】对话框取色&色盘取色的实现
- Cocos2d-x 遮罩的实现 : ClippingNode
- 如何压缩mysql ibdata1文件
- PLA(principal component analysis ) 参考资料
- Servlet生命周期与工作原理
- 有个非计算机专业的问我:怎么学写游戏?
- Android 视频 H.264 编码文章集合
- C++ 字符串反转
- Struts2配置问题