App
SVPickerView.java
Go to the documentation of this file.
1 package mhr.appandroid.views.colorpicker;
2 
3 import mhr.appandroid.R;
4 import android.content.Context;
5 import android.graphics.Bitmap;
6 import android.graphics.BitmapFactory;
7 import android.graphics.Canvas;
8 import android.graphics.Color;
9 import android.graphics.ComposeShader;
10 import android.graphics.LinearGradient;
11 import android.graphics.Paint;
12 import android.graphics.PorterDuff;
13 import android.graphics.Shader;
14 import android.graphics.Shader.TileMode;
15 import android.graphics.drawable.StateListDrawable;
16 import android.os.Bundle;
17 import android.os.Parcelable;
18 import android.util.AttributeSet;
19 import android.view.MotionEvent;
20 import android.view.View;
21 import android.view.ViewParent;
22 import android.widget.Toast;
23 
24 
32 public class SVPickerView extends View {
33  //----- Interface ---------------------------------------------------------------------------------------------------------------------------//
39  public interface OnSVPickerChangeListener {
44  public void onSVPickerChange(SVPickerView picker);
49  public void onSVPickerStartTrackingTouch(SVPickerView picker);
54  public void onSVPickerStopTrackingTouch(SVPickerView picker);
55  }
56 
57  //----- Pole --------------------------------------------------------------------------------------------------------------------------------//
58  protected Bitmap cursor;
59  protected Bitmap cursorPressed;
60  protected Bitmap cursorNormal;
61  @Deprecated
62  protected StateListDrawable drCursor;
63  protected float cursorX;
64  protected int minX;
65  protected int maxX;
66  protected int lengthX;
67  protected float cursorY;
68  protected int minY;
69  protected int maxY;
70  protected int lengthY;
71  protected int margin;
72 
73  protected Paint paint;
74  protected Shader baseShader;
75  protected Shader finalShader;
76 
77  protected float[] actualColor = { 0.0f, 0.0f, 0.0f };
78  protected float[] fullColor = { 0.0f, 1.0f, 1.0f };
79 
81  //----- Accessory a primitivní metody -------------------------------------------------------------------------------------------------------//
82 
88  this.listener = listener;
89  }
90 
95  public float getHue() {
96  return actualColor[0];
97  }
98 
103  public void setHue(float hue) {
104  fullColor[0] = hue;
105  actualColor[0] = hue;
106  finalShader = null;
107  invalidate();
108  }
109 
114  public int getColor() {
115  return Color.HSVToColor(actualColor);
116  }
117 
122  public void getColor(float[] vals) {
123  vals[0] = actualColor[0];
124  vals[1] = actualColor[1];
125  vals[2] = actualColor[2];
126  }
127 
132  public void setColor(int color) {
133  Color.colorToHSV(color, actualColor);
134  fullColor[0] = actualColor[0];
135  cursorX = actualColor[1] * lengthX;
136  cursorY = (1 - actualColor[2]) * lengthY;
137  finalShader = null;
138  invalidate();
139  }
140 
145  public void setColor(float[] hsvColor) {
146  actualColor[0] = hsvColor[0];
147  actualColor[1] = hsvColor[1];
148  actualColor[2] = hsvColor[2];
149  fullColor[0] = actualColor[0];
150  cursorX = actualColor[1] * lengthX;
151  cursorY = (1 - actualColor[2]) * lengthY;
152  finalShader = null;
153  invalidate();
154  }
155 
160  public float getSaturation() {
161  return actualColor[1];
162  }
163 
168  public void setSaturation(float saturation) {
169  actualColor[1] = saturation;
170  cursorX = actualColor[1] * lengthX;
171  invalidate();
172  }
173 
178  public float getValue() {
179  return actualColor[2];
180  }
181 
186  public void setValue(float value) {
187  actualColor[2] = value;
188  cursorY = (1 - actualColor[2]) * lengthY;
189  invalidate();
190  }
191 
192  //----- Pomocné metody ----------------------------------------------------------------------------------------------------------------------//
193  //----- Konstruktory ------------------------------------------------------------------------------------------------------------------------//
194  public SVPickerView(Context context) {
195  super(context);
196  init();
197  }
198 
199  public SVPickerView(Context context, AttributeSet attrs) {
200  super(context, attrs);
201  init();
202  }
203 
204  public SVPickerView(Context context, AttributeSet attrs, int defStyle) {
205  super(context, attrs, defStyle);
206  init();
207  }
208 
212  protected void init() {
213  setLayerType(View.LAYER_TYPE_SOFTWARE, null);
214  cursorPressed = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_control_pressed_bw);
215  cursorNormal = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_control_normal_bw);
217  margin = cursor.getWidth() / 2;
218  paint = new Paint();
219  // drCursor = (StateListDrawable) getResources().getDrawable(R.drawable.bw_scrubber);
220  // drCursor.setState(new int[] { android.R.attr.state_enabled });
221  // margin = drCursor.getIntrinsicWidth() / 2;
222  }
223 
224  @Override
225  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
226  int width = MeasureSpec.getSize(widthMeasureSpec);
227  int height = MeasureSpec.getSize(heightMeasureSpec);
228  // Abychom získaly největší možný čtverec, je nutné nastavit řídící rozměr a ten co se má přizpůsobit na 0. Obrácený postup s hledáním minima nefunguje...
229  if (width < height) {
230  width = height;
231  } else {
232  height = width;
233  }
234  setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
235  }
236 
238  @Override
239  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
240  super.onSizeChanged(w, h, oldw, oldh);
241 
242 // if (getLayoutParams() != null && w != h) {
243 // getLayoutParams().height = w;
244 // setLayoutParams(getLayoutParams());
245 // }
246 
247 
248  minX = margin;
249  maxX = w - margin;
250  lengthX = maxX - margin;
251  minY = margin;
252  maxY = h - margin;
253  lengthY = maxY - margin;
254  cursorX = actualColor[1] * lengthX;
255  cursorY = (1 - actualColor[2]) * lengthY;
256  baseShader = new LinearGradient(minX, minY, minX, maxY, 0xFFFFFFFF, 0xFF000000, TileMode.CLAMP);
257  finalShader = null;
258  }
259 
261  @Override
262  protected void onDraw(Canvas canvas) {
263  if (finalShader == null) {
264  int rgb = Color.HSVToColor(fullColor);
265  Shader topShader = new LinearGradient(minX, minY, maxX, minY, 0xffffffff, rgb, TileMode.CLAMP);
266  finalShader = new ComposeShader(baseShader, topShader, PorterDuff.Mode.MULTIPLY);
267  paint.setShader(finalShader);
268  }
269  canvas.drawRect(minX, minY, maxX, maxY, paint);
270  canvas.drawBitmap(cursor, cursorX, cursorY, null);
271  }
272 
274  @Override
275  public boolean onTouchEvent(MotionEvent ev) {
276  switch (ev.getAction()) {
277  case MotionEvent.ACTION_DOWN:
279  // drCursor.setState(new int[] {android.R.attr.state_pressed, android.R.attr.state_enabled});
280  break;
281  case MotionEvent.ACTION_UP:
283  // drCursor.setState(new int[] {android.R.attr.state_enabled});
284  break;
285  }
286  float x = ev.getX();
287  float y = ev.getY();
288  if (x < minX) {
289  cursorX = 0;
290  } else if (x > maxX) {
291  cursorX = maxX - margin;
292  } else {
293  cursorX = (int) x - margin;
294  }
295  if (y < minY) {
296  cursorY = 0;
297  } else if (y > maxY) {
298  cursorY = maxY - margin;
299  } else {
300  cursorY = (int) y - margin;
301  }
302  actualColor[1] = cursorX / lengthX;
303  actualColor[2] = 1 - cursorY / lengthY;
304  if (listener != null) {
305  switch (ev.getAction()) {
306  case MotionEvent.ACTION_DOWN:
308  break;
309  case MotionEvent.ACTION_UP:
311  break;
312  }
314  }
315  invalidate();
316  ViewParent parent = getParent();
317  if (parent != null) {
318  parent.requestDisallowInterceptTouchEvent(true);
319  }
320  return true;
321  }
322 }