23
23
import android .graphics .Bitmap ;
24
24
import android .graphics .Color ;
25
25
import android .graphics .PointF ;
26
+ import android .graphics .RectF ;
26
27
import android .graphics .drawable .Drawable ;
27
28
import android .net .Uri ;
28
29
import android .os .Build ;
32
33
import android .util .Log ;
33
34
import android .view .Menu ;
34
35
import android .view .MenuItem ;
36
+ import android .view .MotionEvent ;
37
+ import android .view .SoundEffectConstants ;
35
38
import android .view .View ;
39
+ import android .view .ViewConfiguration ;
36
40
import android .view .ViewGroup ;
37
41
import android .view .WindowManager ;
38
- import android .view .animation .Animation ;
39
42
import android .view .animation .AnimationUtils ;
40
43
import android .widget .ImageView ;
41
44
import android .widget .RelativeLayout ;
@@ -75,8 +78,8 @@ public class TicQRActivity extends DecoderActivity {
75
78
private float mBoxSize ;
76
79
77
80
private String mDestinationEmail ;
78
- private final ArrayList <TickBoxHolder > mServerTickBoxes = new ArrayList <TickBoxHolder >();
79
- private ArrayList <PointF > mImageTickBoxes = new ArrayList <PointF >();
81
+ private final ArrayList <TickBoxHolder > mServerTickBoxes = new ArrayList <>();
82
+ private ArrayList <PointF > mImageTickBoxes = new ArrayList <>();
80
83
81
84
private boolean mBoxesLoaded = false ;
82
85
private boolean mImageParsed = false ;
@@ -128,6 +131,7 @@ public void onCreate(Bundle savedInstanceState) {
128
131
setResizeImageToView (true ); // a lower-quality image
129
132
130
133
mImageView = (ImageView ) findViewById (R .id .image_view );
134
+ mImageView .setOnTouchListener (mImageTouchListener );
131
135
132
136
// set up action bar
133
137
ActionBar actionBar = getSupportActionBar ();
@@ -358,15 +362,7 @@ private void verifyBoxes() {
358
362
359
363
// second pass - un-tick any boxes that are still marked as ticked, but are actually outside the image,
360
364
// then add an animated tick box on those that remain
361
- RelativeLayout highlightHolder = (RelativeLayout ) findViewById (R .id .tick_highlight_holder );
362
- Animation pulse = AnimationUtils .loadAnimation (this , R .anim .pulse );
363
- int tickIcon = R .drawable .ic_highlight_tick ;
364
- Drawable tickDrawable = getResources ().getDrawable (tickIcon );
365
- int iconWidth = tickDrawable .getIntrinsicWidth ();
366
- int iconHeight = tickDrawable .getIntrinsicHeight ();
367
-
368
365
boolean tickedBoxes = false ;
369
- StringBuilder itemsBuilder = new StringBuilder ();
370
366
for (TickBoxHolder tickBox : mServerTickBoxes ) {
371
367
if (tickBox .ticked ) {
372
368
PointF imagePosition = tickBox .imagePosition ;
@@ -384,36 +380,123 @@ private void verifyBoxes() {
384
380
385
381
if (tickBox .ticked ) {
386
382
Log .d (TAG , "Ticked box (" + tickBox .description + ") found at " + imagePosition .x + "," +
387
- + imagePosition .y );
383
+ +imagePosition .y );
388
384
385
+ // add a tick overlay on each ticked box, and allow clicking to tick/un-tick any box
386
+ addTickHighlight (tickBox );
389
387
tickedBoxes = true ;
390
- itemsBuilder .append (getString (R .string .email_item , tickBox .quantity , tickBox .description ));
391
-
392
- ImageView tickHighlight = new ImageView (TicQRActivity .this );
393
- tickHighlight .setImageResource (tickIcon );
394
- RelativeLayout .LayoutParams layoutParams = new RelativeLayout .LayoutParams (ViewGroup .LayoutParams
395
- .WRAP_CONTENT , ViewGroup .LayoutParams .WRAP_CONTENT );
396
- layoutParams .leftMargin = mImageView .getLeft () + Math .round (imagePosition .x ) - (iconWidth / 2 );
397
- layoutParams .topMargin = mImageView .getTop () + Math .round (imagePosition .y ) - (iconHeight / 2 );
398
-
399
- highlightHolder .addView (tickHighlight , layoutParams );
400
- tickHighlight .startAnimation (pulse );
401
388
}
402
389
}
403
390
}
404
391
405
392
findViewById (R .id .parse_progress ).setVisibility (View .GONE );
406
393
407
394
getSupportActionBar ().setTitle (R .string .title_activity_order );
408
- supportInvalidateOptionsMenu (); // to show the place order button & rescan option
409
- if (tickedBoxes ) {
410
- mEmailContents = itemsBuilder .toString ();
411
- Toast .makeText (TicQRActivity .this , getString (R .string .hint_send_order ), Toast .LENGTH_SHORT ).show ();
412
- } else {
413
- Toast .makeText (TicQRActivity .this , getString (R .string .hint_no_boxes_found ), Toast .LENGTH_SHORT ).show ();
395
+ mEmailContents = getEmailMessage ();
396
+ supportInvalidateOptionsMenu (); // to show the place order button (if required) & rescan option
397
+ Toast .makeText (TicQRActivity .this , tickedBoxes ? R .string .hint_send_order : R .string .hint_no_boxes_found ,
398
+ Toast .LENGTH_SHORT ).show ();
399
+ }
400
+
401
+ private String getEmailMessage () {
402
+ StringBuilder itemsBuilder = new StringBuilder ();
403
+ for (TickBoxHolder tickBox : mServerTickBoxes ) {
404
+ if (tickBox .ticked ) {
405
+ itemsBuilder .append (getString (R .string .email_item , tickBox .quantity , tickBox .description ));
406
+ }
414
407
}
408
+ if (itemsBuilder .length () > 0 ) {
409
+ return itemsBuilder .toString ();
410
+ }
411
+ return null ;
415
412
}
416
413
414
+ private void addTickHighlight (TickBoxHolder tickBox ) {
415
+ int tickIcon = R .drawable .ic_highlight_tick ;
416
+ Drawable tickDrawable = getResources ().getDrawable (tickIcon );
417
+
418
+ ImageView tickHighlight = new ImageView (TicQRActivity .this );
419
+ tickHighlight .setImageResource (tickIcon );
420
+ RelativeLayout .LayoutParams layoutParams = new RelativeLayout .LayoutParams (ViewGroup .LayoutParams
421
+ .WRAP_CONTENT , ViewGroup .LayoutParams .WRAP_CONTENT );
422
+ layoutParams .leftMargin = mImageView .getLeft () + Math .round (tickBox .imagePosition .x ) - (tickDrawable
423
+ .getIntrinsicWidth () / 2 );
424
+ layoutParams .topMargin = mImageView .getTop () + Math .round (tickBox .imagePosition .y ) - (tickDrawable
425
+ .getIntrinsicHeight () / 2 );
426
+
427
+ ((RelativeLayout ) findViewById (R .id .tick_highlight_holder )).addView (tickHighlight , layoutParams );
428
+ tickHighlight .startAnimation (AnimationUtils .loadAnimation (this , R .anim .pulse ));
429
+
430
+ tickHighlight .setOnClickListener (mTickClickListener );
431
+ tickHighlight .setTag (tickBox );
432
+ }
433
+
434
+ private final View .OnClickListener mTickClickListener = new View .OnClickListener () {
435
+ @ Override
436
+ public void onClick (View view ) {
437
+ TickBoxHolder holder = (TickBoxHolder ) view .getTag ();
438
+ if (holder .ticked ) {
439
+ holder .ticked = false ;
440
+ ((RelativeLayout ) view .getParent ()).removeView (view );
441
+ mEmailContents = getEmailMessage ();
442
+ supportInvalidateOptionsMenu (); // to hide the place order button if necessary
443
+ }
444
+ }
445
+ };
446
+
447
+ private final View .OnTouchListener mImageTouchListener = new View .OnTouchListener () {
448
+ private float mDownX ;
449
+ private float mDownY ;
450
+ private boolean mCanClick ;
451
+ private float mScaledTouchSlop = -1 ;
452
+
453
+ @ Override
454
+ public boolean onTouch (View view , MotionEvent event ) {
455
+ switch (event .getAction ()) {
456
+ case MotionEvent .ACTION_DOWN :
457
+ if (mScaledTouchSlop < 0 ) {
458
+ mScaledTouchSlop = ViewConfiguration .get (TicQRActivity .this ).getScaledTouchSlop ();
459
+ }
460
+ mDownX = event .getX ();
461
+ mDownY = event .getY ();
462
+ mCanClick = true ;
463
+ break ;
464
+
465
+ case MotionEvent .ACTION_MOVE :
466
+ final float scrollX = mDownX - event .getX ();
467
+ final float scrollY = mDownY - event .getY ();
468
+ final float dist = (float ) Math .sqrt (scrollX * scrollX + scrollY * scrollY );
469
+ if (dist >= mScaledTouchSlop ) {
470
+ mCanClick = false ;
471
+ }
472
+ break ;
473
+
474
+ case MotionEvent .ACTION_UP :
475
+ if (mCanClick ) {
476
+ view .playSoundEffect (SoundEffectConstants .CLICK ); // so we get the click sound
477
+ float imageX = event .getX ();
478
+ float imageY = event .getY ();
479
+ float boxSize = mBoxSize ; // mBoxSize is total width, but allow to give a larger click area
480
+ RectF comparisonRect = new RectF ();
481
+ for (TickBoxHolder tickBox : mServerTickBoxes ) {
482
+ PointF position = tickBox .imagePosition ;
483
+ comparisonRect .set (position .x - boxSize , position .y - boxSize , position .x + boxSize ,
484
+ position .y + boxSize );
485
+ if (!tickBox .ticked && comparisonRect .contains (imageX , imageY )) {
486
+ tickBox .ticked = true ;
487
+ addTickHighlight (tickBox );
488
+ mEmailContents = getEmailMessage ();
489
+ supportInvalidateOptionsMenu (); // to show the place order button
490
+ break ;
491
+ }
492
+ }
493
+ }
494
+ break ;
495
+ }
496
+ return true ;
497
+ }
498
+ };
499
+
417
500
private void sendOrder () {
418
501
try {
419
502
Intent emailIntent = new Intent (Intent .ACTION_SENDTO , Uri .fromParts ("mailto" ,
0 commit comments