App
CropPicker.java
Go to the documentation of this file.
1 package mhr.appandroid.views;
2 
3 import java.util.Arrays;
4 
5 import mhr.appandroid.R;
6 import android.content.Context;
7 import android.graphics.Bitmap;
8 import android.graphics.BitmapFactory;
9 import android.graphics.Canvas;
10 import android.graphics.Paint;
11 import android.graphics.Path;
12 import android.graphics.Paint.Style;
13 import android.graphics.Path.Direction;
14 import android.graphics.RectF;
15 import android.graphics.drawable.ShapeDrawable;
16 import android.graphics.drawable.shapes.PathShape;
17 import android.graphics.Rect;
18 import android.util.AttributeSet;
19 import android.view.MotionEvent;
20 import android.view.View;
21 
22 public class CropPicker extends View {
23 
24  //===== INTERFACES, CLASSES, ENUMS ==========================================================================================================//
25  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
26  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
27 
28  public static interface CropPickerEventListener {
29  public void onStartTrackingCrop(CropPicker p);
30  public void onCropChanged(CropPicker p);
31  public void onStopTrackingCrop(CropPicker p);
32  }
33 
34 
35  //===== FIELDS ==============================================================================================================================//
36  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
37  protected Bitmap cPressed;
38  protected Bitmap cNormal;
39  protected Rect cRect;
40 
41  protected Paint bgPaint;
42  protected Paint lnPaint;
43 
44  protected Rect[] curs;
45  protected Rect selCur = null;
46  protected int selCutIndex;
47 
48  protected RectF crop;
49  protected RectF maxRect;
50 
51  protected float lastX;
52  protected float lastY;
53 
54  protected int cWidth;
55  protected int cHeight;
56  protected int cXCenter;
57  protected int cYCenter;
58 
60 
61  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
62 
63  //===== CONSTRUCTORS, DESTRUCTORS, RELATED METHODS ==========================================================================================//
64  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
65  protected void init() {
66  setLayerType(View.LAYER_TYPE_SOFTWARE, null);
67  cPressed = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_control_pressed_bw);
68  cNormal = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_control_normal_bw);
69 
70  bgPaint = new Paint();
71  bgPaint.setColor(0xFF545454);
72 
73  lnPaint = new Paint();
74  lnPaint.setColor(0xFFFFFFFF);
75  lnPaint.setStyle(Style.STROKE);
76  lnPaint.setStrokeWidth(5);
77  lnPaint.setAntiAlias(true);
78 
79  cWidth = cNormal.getWidth();
80  cHeight = cNormal.getHeight();
81 
82  cXCenter = cWidth / 2;
83  cYCenter = cHeight / 2;
84 
85  cRect = new Rect(0, 0, cNormal.getWidth(), cNormal.getHeight());
86  }
87  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
88  public CropPicker(Context context) {
89  super(context);
90  init();
91  }
92 
93  public CropPicker(Context context, AttributeSet attrs) {
94  super(context, attrs);
95  init();
96  }
97 
98  public CropPicker(Context context, AttributeSet attrs, int defStyle) {
99  super(context, attrs, defStyle);
100  init();
101  }
102 
103  //===== METHODS =============================================================================================================================//
104  //----- NON-PUBLIC --------------------------------------------------------------------------------------------------------------------------//
105  protected void updateRects() {
106 
107  Rect r;
108 
109  r = curs[0];
110  r.left = (int)(crop.left - cXCenter);
111  r.top = (int)(crop.top - cYCenter);
112  r.right = (int)(crop.left + cWidth - cXCenter);
113  r.bottom = (int)(crop.top + cHeight - cYCenter);
114 
115  r = curs[1];
116  r.left = (int)(crop.right - cXCenter);
117  r.top = (int)(crop.top - cYCenter);
118  r.right = (int)(crop.right + cWidth - cXCenter);
119  r.bottom = (int)(crop.top + cHeight - cYCenter);
120 
121  r = curs[2];
122  r.left = (int)(crop.left - cXCenter);
123  r.top = (int)(crop.bottom - cYCenter);
124  r.right = (int)(crop.left + cWidth - cXCenter);
125  r.bottom = (int)(crop.bottom + cHeight - cYCenter);
126 
127  r = curs[3];
128  r.left = (int)(crop.right - cXCenter);
129  r.top = (int)(crop.bottom - cYCenter);
130  r.right = (int)(crop.right + cWidth - cXCenter);
131  r.bottom = (int)(crop.bottom + cHeight - cYCenter);
132  }
133 
134  //----- PUBLIC ------------------------------------------------------------------------------------------------------------------------------//
135 
137  listener = l;
138  }
139 
140  public RectF getCrop() {
141  return new RectF(crop);
142  }
143 
144  public void setCrop(RectF crop) {
145  this.crop = crop;
146  invalidate();
147  }
148 
149  public void resetCrop() {
150  crop = new RectF(maxRect.right / 4, maxRect.bottom / 4, 3 * maxRect.right / 4, 3 * maxRect.bottom / 4);
151  invalidate();
152  }
153  //===== CALLBACKS ===========================================================================================================================//
154 
155  @Override
156  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
157  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
158  }
159 
161  @Override
162  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
163  super.onSizeChanged(w, h, oldw, oldh);
164 
165  maxRect = new RectF(0, 0, w, h);
166  crop = new RectF(w / 4, h / 4, 3 * w / 4, 3 * h / 4);
167 
168  curs = new Rect[] { new Rect(), new Rect(),new Rect(),new Rect() };
169  }
170 
172  @Override
173  protected void onDraw(Canvas canvas) {
174  updateRects();
175  canvas.drawColor(0x00000000);
176 
177  Path pth = new Path();
178  pth.addRect(0, 0, maxRect.right, crop.top, Direction.CW);
179  pth.addRect(0, crop.top, crop.left, crop.bottom, Direction.CW);
180  pth.addRect(crop.right, crop.top, maxRect.right, crop.bottom, Direction.CW);
181  pth.addRect(0, crop.bottom, maxRect.right, maxRect.bottom, Direction.CW);
182  ShapeDrawable sdr = new ShapeDrawable(new PathShape(pth, maxRect.width(), maxRect.height()));
183  Paint paint = sdr.getPaint();
184  paint.setStyle(Style.FILL);
185  paint.setColor(0xAA000000);
186  sdr.setBounds((int)maxRect.left, (int)maxRect.top, (int)maxRect.right, (int)maxRect.bottom);
187  sdr.draw(canvas);
188 
189  canvas.drawLines(new float[] {
190  crop.left, crop.top, crop.right, crop.top,
191  crop.left, crop.top, crop.left, crop.bottom,
192  crop.left, crop.bottom, crop.right, crop.bottom,
193  crop.right, crop.top, crop.right, crop.bottom,
194  }, lnPaint);
195 
196  for (Rect r : curs) {
197  if (r == selCur) {
198  canvas.drawBitmap(cPressed, null, r, null);
199  } else {
200  canvas.drawBitmap(cNormal, null, r, null);
201  }
202  }
203  }
204 
205  @Override
206  public boolean onTouchEvent(MotionEvent ev) {
207  float x = ev.getX();
208  float y = ev.getY();
209 
210  switch (ev.getAction()) {
211  case MotionEvent.ACTION_DOWN:
212  for (int i = 0; i < curs.length; i++) {
213  if (curs[i].contains((int)x, (int)y)) {
214  selCur = curs[i];
215  selCutIndex = i;
216  break;
217  }
218  }
219  if (selCur != null) {
220  lastX = x;
221  lastY = y;
222  if (listener != null) {
224  }
225  }
226  break;
227  case MotionEvent.ACTION_MOVE:
228  if (selCur != null) {
229  switch (selCutIndex) {
230  case 0:
231  crop.left += x - lastX;
232  crop.left = (crop.left < crop.right) ? crop.left : crop.right;
233  crop.top += y - lastY;
234  crop.top = (crop.top < crop.bottom) ? crop.top : crop.bottom;
235  break;
236  case 1:
237  crop.right += x - lastX;
238  crop.right = (crop.left < crop.right) ? crop.right : crop.left;
239  crop.top += y - lastY;
240  crop.top = (crop.top < crop.bottom) ? crop.top : crop.bottom;
241  break;
242  case 2:
243  crop.left += x - lastX;
244  crop.left = (crop.left < crop.right) ? crop.left : crop.right;
245  crop.bottom += y - lastY;
246  crop.bottom = (crop.top < crop.bottom) ? crop.bottom : crop.top;
247  break;
248  case 3:
249  crop.right += x - lastX;
250  crop.right = (crop.left < crop.right) ? crop.right : crop.left;
251  crop.bottom += y - lastY;
252  crop.bottom = (crop.top < crop.bottom) ? crop.bottom : crop.top;
253  break;
254  default:
255  break;
256  }
257  lastX = x;
258  lastY = y;
259 
260  crop.setIntersect(maxRect, crop);
261 
262  if (listener != null) {
263  listener.onCropChanged(this);
264  }
265  invalidate();
266  }
267  break;
268  case MotionEvent.ACTION_UP:
269  if (selCur != null) {
270  selCur = null;
271  if (listener != null) {
273  }
274  invalidate();
275  }
276  break;
277  }
278  return true;
279  }
280 }