歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 顏色選擇器(ColorPicker)

Android 顏色選擇器(ColorPicker)

日期:2017/3/1 10:40:30   编辑:Linux編程

因為畫圖板中需要使用顏色選擇器. 去查了下api demo, 發現有現成的ColorPickerDialog, 但是功能比較簡單, 主要是無法選擇黑色和白色. 之後也去網上找了下, 倒是發現了幾個, 但是用著感覺不太好.就想著自己重寫個好了.

先上圖

1.測試界面

2. 調色板對話框

3. 選擇顏色

4.改變字體顏色


調色板對話框

ColorPickerDialog.java

Java代碼

  1. package com.dwood.paintdemo;
  2. import Android.app.Dialog;
  3. import android.content.Context;
  4. import android.graphics.Canvas;
  5. import android.graphics.Color;
  6. import android.graphics.LinearGradient;
  7. import android.graphics.Paint;
  8. import android.graphics.RectF;
  9. import android.graphics.Shader;
  10. import android.graphics.SweepGradient;
  11. import android.os.Bundle;
  12. import android.util.Log;
  13. import android.view.MotionEvent;
  14. import android.view.View;
  15. import android.view.WindowManager;
  16. public class ColorPickerDialog extends Dialog {
  17. private final boolean debug = true;
  18. private final String TAG = "ColorPicker";
  19. Context context;
  20. private String title;//標題
  21. private int mInitialColor;//初始顏色
  22. private OnColorChangedListener mListener;
  23. /**
  24. * 初始顏色黑色
  25. * @param context
  26. * @param title 對話框標題
  27. * @param listener 回調
  28. */
  29. public ColorPickerDialog(Context context, String title,
  30. OnColorChangedListener listener) {
  31. this(context, Color.BLACK, title, listener);
  32. }
  33. /**
  34. *
  35. * @param context
  36. * @param initialColor 初始顏色
  37. * @param title 標題
  38. * @param listener 回調
  39. */
  40. public ColorPickerDialog(Context context, int initialColor,
  41. String title, OnColorChangedListener listener) {
  42. super(context);
  43. this.context = context;
  44. mListener = listener;
  45. mInitialColor = initialColor;
  46. this.title = title;
  47. }
  48. @Override
  49. protected void onCreate(Bundle savedInstanceState) {
  50. super.onCreate(savedInstanceState);
  51. WindowManager manager = getWindow().getWindowManager();
  52. int height = (int) (manager.getDefaultDisplay().getHeight() * 0.5f);
  53. int width = (int) (manager.getDefaultDisplay().getWidth() * 0.7f);
  54. ColorPickerView myView = new ColorPickerView(context, height, width);
  55. setContentView(myView);
  56. setTitle(title);
  57. }
  58. private class ColorPickerView extends View {
  59. private Paint mPaint;//漸變色環畫筆
  60. private Paint mCenterPaint;//中間圓畫筆
  61. private Paint mLinePaint;//分隔線畫筆
  62. private Paint mRectPaint;//漸變方塊畫筆
  63. private Shader rectShader;//漸變方塊漸變圖像
  64. private float rectLeft;//漸變方塊左x坐標
  65. private float rectTop;//漸變方塊右x坐標
  66. private float rectRight;//漸變方塊上y坐標
  67. private float rectBottom;//漸變方塊下y坐標
  68. private final int[] mCircleColors;//漸變色環顏色
  69. private final int[] mRectColors;//漸變方塊顏色
  70. private int mHeight;//View高
  71. private int mWidth;//View寬
  72. private float r;//色環半徑(paint中部)
  73. private float centerRadius;//中心圓半徑
  74. private boolean downInCircle = true;//按在漸變環上
  75. private boolean downInRect;//按在漸變方塊上
  76. private boolean highlightCenter;//高亮
  77. private boolean highlightCenterLittle;//微亮
  78. public ColorPickerView(Context context, int height, int width) {
  79. super(context);
  80. this.mHeight = height - 36;
  81. this.mWidth = width;
  82. setMinimumHeight(height - 36);
  83. setMinimumWidth(width);
  84. //漸變色環參數
  85. mCircleColors = new int[] {0xFFFF0000, 0xFFFF00FF, 0xFF0000FF,
  86. 0xFF00FFFF, 0xFF00FF00,0xFFFFFF00, 0xFFFF0000};
  87. Shader s = new SweepGradient(0, 0, mCircleColors, null);
  88. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  89. mPaint.setShader(s);
  90. mPaint.setStyle(Paint.Style.STROKE);
  91. mPaint.setStrokeWidth(50);
  92. r = width / 2 * 0.7f - mPaint.getStrokeWidth() * 0.5f;
  93. //中心圓參數
  94. mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  95. mCenterPaint.setColor(mInitialColor);
  96. mCenterPaint.setStrokeWidth(5);
  97. centerRadius = (r - mPaint.getStrokeWidth() / 2 ) * 0.7f;
  98. //邊框參數
  99. mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  100. mLinePaint.setColor(Color.parseColor("#72A1D1"));
  101. mLinePaint.setStrokeWidth(4);
  102. //黑白漸變參數
  103. mRectColors = new int[]{0xFF000000, mCenterPaint.getColor(), 0xFFFFFFFF};
  104. mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  105. mRectPaint.setStrokeWidth(5);
  106. rectLeft = -r - mPaint.getStrokeWidth() * 0.5f;
  107. rectTop = r + mPaint.getStrokeWidth() * 0.5f +
  108. mLinePaint.getStrokeMiter() * 0.5f + 15;
  109. rectRight = r + mPaint.getStrokeWidth() * 0.5f;
  110. rectBottom = rectTop + 50;
  111. }
  112. @Override
  113. protected void onDraw(Canvas canvas) {
  114. //移動中心
  115. canvas.translate(mWidth / 2, mHeight / 2 - 50);
  116. //畫中心圓
  117. canvas.drawCircle(0, 0, centerRadius, mCenterPaint);
  118. //是否顯示中心圓外的小圓環
  119. if (highlightCenter || highlightCenterLittle) {
  120. int c = mCenterPaint.getColor();
  121. mCenterPaint.setStyle(Paint.Style.STROKE);
  122. if(highlightCenter) {
  123. mCenterPaint.setAlpha(0xFF);
  124. }else if(highlightCenterLittle) {
  125. mCenterPaint.setAlpha(0x90);
  126. }
  127. canvas.drawCircle(0, 0,
  128. centerRadius + mCenterPaint.getStrokeWidth(), mCenterPaint);
  129. mCenterPaint.setStyle(Paint.Style.FILL);
  130. mCenterPaint.setColor(c);
  131. }
  132. //畫色環
  133. canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
  134. //畫黑白漸變塊
  135. if(downInCircle) {
  136. mRectColors[1] = mCenterPaint.getColor();
  137. }
  138. rectShader = new LinearGradient(rectLeft, 0, rectRight, 0, mRectColors, null, Shader.TileMode.MIRROR);
  139. mRectPaint.setShader(rectShader);
  140. canvas.drawRect(rectLeft, rectTop, rectRight, rectBottom, mRectPaint);
  141. float offset = mLinePaint.getStrokeWidth() / 2;
  142. canvas.drawLine(rectLeft - offset, rectTop - offset * 2,
  143. rectLeft - offset, rectBottom + offset * 2, mLinePaint);//左
  144. canvas.drawLine(rectLeft - offset * 2, rectTop - offset,
  145. rectRight + offset * 2, rectTop - offset, mLinePaint);//上
  146. canvas.drawLine(rectRight + offset, rectTop - offset * 2,
  147. rectRight + offset, rectBottom + offset * 2, mLinePaint);//右
  148. canvas.drawLine(rectLeft - offset * 2, rectBottom + offset,
  149. rectRight + offset * 2, rectBottom + offset, mLinePaint);//下
  150. super.onDraw(canvas);
  151. }
  152. @Override
  153. public boolean onTouchEvent(MotionEvent event) {
  154. float x = event.getX() - mWidth / 2;
  155. float y = event.getY() - mHeight / 2 + 50;
  156. boolean inCircle = inColorCircle(x, y,
  157. r + mPaint.getStrokeWidth() / 2, r - mPaint.getStrokeWidth() / 2);
  158. boolean inCenter = inCenter(x, y, centerRadius);
  159. boolean inRect = inRect(x, y);
  160. switch (event.getAction()) {
  161. case MotionEvent.ACTION_DOWN:
  162. downInCircle = inCircle;
  163. downInRect = inRect;
  164. highlightCenter = inCenter;
  165. case MotionEvent.ACTION_MOVE:
  166. if(downInCircle && inCircle) {//down按在漸變色環內, 且move也在漸變色環內
  167. float angle = (float) Math.atan2(y, x);
  168. float unit = (float) (angle / (2 * Math.PI));
  169. if (unit < 0) {
  170. unit += 1;
  171. }
  172. mCenterPaint.setColor(interpCircleColor(mCircleColors, unit));
  173. if(debug) Log.v(TAG, "色環內, 坐標: " + x + "," + y);
  174. }else if(downInRect && inRect) {//down在漸變方塊內, 且move也在漸變方塊內
  175. mCenterPaint.setColor(interpRectColor(mRectColors, x));
  176. }
  177. if(debug) Log.v(TAG, "[MOVE] 高亮: " + highlightCenter + "微亮: " + highlightCenterLittle + " 中心: " + inCenter);
  178. if((highlightCenter && inCenter) || (highlightCenterLittle && inCenter)) {//點擊中心圓, 當前移動在中心圓
  179. highlightCenter = true;
  180. highlightCenterLittle = false;
  181. } else if(highlightCenter || highlightCenterLittle) {//點擊在中心圓, 當前移出中心圓
  182. highlightCenter = false;
  183. highlightCenterLittle = true;
  184. } else {
  185. highlightCenter = false;
  186. highlightCenterLittle = false;
  187. }
  188. invalidate();
  189. break;
  190. case MotionEvent.ACTION_UP:
  191. if(highlightCenter && inCenter) {//點擊在中心圓, 且當前啟動在中心圓
  192. if(mListener != null) {
  193. mListener.colorChanged(mCenterPaint.getColor());
  194. ColorPickerDialog.this.dismiss();
  195. }
  196. }
  197. if(downInCircle) {
  198. downInCircle = false;
  199. }
  200. if(downInRect) {
  201. downInRect = false;
  202. }
  203. if(highlightCenter) {
  204. highlightCenter = false;
  205. }
  206. if(highlightCenterLittle) {
  207. highlightCenterLittle = false;
  208. }
  209. invalidate();
  210. break;
  211. }
  212. return true;
  213. }
  214. @Override
  215. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  216. super.onMeasure(mWidth, mHeight);
  217. }
  218. /**
  219. * 坐標是否在色環上
  220. * @param x 坐標
  221. * @param y 坐標
  222. * @param outRadius 色環外半徑
  223. * @param inRadius 色環內半徑
  224. * @return
  225. */
  226. private boolean inColorCircle(float x, float y, float outRadius, float inRadius) {
  227. double outCircle = Math.PI * outRadius * outRadius;
  228. double inCircle = Math.PI * inRadius * inRadius;
  229. double fingerCircle = Math.PI * (x * x + y * y);
  230. if(fingerCircle < outCircle && fingerCircle > inCircle) {
  231. return true;
  232. }else {
  233. return false;
  234. }
  235. }
  236. /**
  237. * 坐標是否在中心圓上
  238. * @param x 坐標
  239. * @param y 坐標
  240. * @param centerRadius 圓半徑
  241. * @return
  242. */
  243. private boolean inCenter(float x, float y, float centerRadius) {
  244. double centerCircle = Math.PI * centerRadius * centerRadius;
  245. double fingerCircle = Math.PI * (x * x + y * y);
  246. if(fingerCircle < centerCircle) {
  247. return true;
  248. }else {
  249. return false;
  250. }
  251. }
  252. /**
  253. * 坐標是否在漸變色中
  254. * @param x
  255. * @param y
  256. * @return
  257. */
  258. private boolean inRect(float x, float y) {
  259. if( x <= rectRight && x >=rectLeft && y <= rectBottom && y >=rectTop) {
  260. return true;
  261. } else {
  262. return false;
  263. }
  264. }
  265. /**
  266. * 獲取圓環上顏色
  267. * @param colors
  268. * @param unit
  269. * @return
  270. */
  271. private int interpCircleColor(int colors[], float unit) {
  272. if (unit <= 0) {
  273. return colors[0];
  274. }
  275. if (unit >= 1) {
  276. return colors[colors.length - 1];
  277. }
  278. float p = unit * (colors.length - 1);
  279. int i = (int)p;
  280. p -= i;
  281. // now p is just the fractional part [0...1) and i is the index
  282. int c0 = colors[i];
  283. int c1 = colors[i+1];
  284. int a = ave(Color.alpha(c0), Color.alpha(c1), p);
  285. int r = ave(Color.red(c0), Color.red(c1), p);
  286. int g = ave(Color.green(c0), Color.green(c1), p);
  287. int b = ave(Color.blue(c0), Color.blue(c1), p);
  288. return Color.argb(a, r, g, b);
  289. }
  290. /**
  291. * 獲取漸變塊上顏色
  292. * @param colors
  293. * @param x
  294. * @return
  295. */
  296. private int interpRectColor(int colors[], float x) {
  297. int a, r, g, b, c0, c1;
  298. float p;
  299. if (x < 0) {
  300. c0 = colors[0];
  301. c1 = colors[1];
  302. p = (x + rectRight) / rectRight;
  303. } else {
  304. c0 = colors[1];
  305. c1 = colors[2];
  306. p = x / rectRight;
  307. }
  308. a = ave(Color.alpha(c0), Color.alpha(c1), p);
  309. r = ave(Color.red(c0), Color.red(c1), p);
  310. g = ave(Color.green(c0), Color.green(c1), p);
  311. b = ave(Color.blue(c0), Color.blue(c1), p);
  312. return Color.argb(a, r, g, b);
  313. }
  314. private int ave(int s, int d, float p) {
  315. return s + Math.round(p * (d - s));
  316. }
  317. }
  318. /**
  319. * 回調接口
  320. * @author <a href="[email protected]">LynK</a>
  321. *
  322. * Create on 2012-1-6 上午8:21:05
  323. *
  324. */
  325. public interface OnColorChangedListener {
  326. /**
  327. * 回調函數
  328. * @param color 選中的顏色
  329. */
  330. void colorChanged(int color);
  331. }
  332. public String getTitle() {
  333. return title;
  334. }
  335. public void setTitle(String title) {
  336. this.title = title;
  337. }
  338. public int getmInitialColor() {
  339. return mInitialColor;
  340. }
  341. public void setmInitialColor(int mInitialColor) {
  342. this.mInitialColor = mInitialColor;
  343. }
  344. public OnColorChangedListener getmListener() {
  345. return mListener;
  346. }
  347. public void setmListener(OnColorChangedListener mListener) {
  348. this.mListener = mListener;
  349. }
  350. }
Copyright © Linux教程網 All Rights Reserved