Skip to content

Commit 59db328

Browse files
committed
Version 1.0
Enabled selecting/unselecting boxes after scanning Also made language level changes for Java 1.7
1 parent f63f2e1 commit 59db328

File tree

2 files changed

+116
-33
lines changed

2 files changed

+116
-33
lines changed

app/src/main/java/ac/robinson/ticqr/TicQRActivity.java

Lines changed: 112 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.graphics.Bitmap;
2424
import android.graphics.Color;
2525
import android.graphics.PointF;
26+
import android.graphics.RectF;
2627
import android.graphics.drawable.Drawable;
2728
import android.net.Uri;
2829
import android.os.Build;
@@ -32,10 +33,12 @@
3233
import android.util.Log;
3334
import android.view.Menu;
3435
import android.view.MenuItem;
36+
import android.view.MotionEvent;
37+
import android.view.SoundEffectConstants;
3538
import android.view.View;
39+
import android.view.ViewConfiguration;
3640
import android.view.ViewGroup;
3741
import android.view.WindowManager;
38-
import android.view.animation.Animation;
3942
import android.view.animation.AnimationUtils;
4043
import android.widget.ImageView;
4144
import android.widget.RelativeLayout;
@@ -75,8 +78,8 @@ public class TicQRActivity extends DecoderActivity {
7578
private float mBoxSize;
7679

7780
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<>();
8083

8184
private boolean mBoxesLoaded = false;
8285
private boolean mImageParsed = false;
@@ -128,6 +131,7 @@ public void onCreate(Bundle savedInstanceState) {
128131
setResizeImageToView(true); // a lower-quality image
129132

130133
mImageView = (ImageView) findViewById(R.id.image_view);
134+
mImageView.setOnTouchListener(mImageTouchListener);
131135

132136
// set up action bar
133137
ActionBar actionBar = getSupportActionBar();
@@ -358,15 +362,7 @@ private void verifyBoxes() {
358362

359363
// second pass - un-tick any boxes that are still marked as ticked, but are actually outside the image,
360364
// 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-
368365
boolean tickedBoxes = false;
369-
StringBuilder itemsBuilder = new StringBuilder();
370366
for (TickBoxHolder tickBox : mServerTickBoxes) {
371367
if (tickBox.ticked) {
372368
PointF imagePosition = tickBox.imagePosition;
@@ -384,36 +380,123 @@ private void verifyBoxes() {
384380

385381
if (tickBox.ticked) {
386382
Log.d(TAG, "Ticked box (" + tickBox.description + ") found at " + imagePosition.x + "," +
387-
+ imagePosition.y);
383+
+imagePosition.y);
388384

385+
// add a tick overlay on each ticked box, and allow clicking to tick/un-tick any box
386+
addTickHighlight(tickBox);
389387
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);
401388
}
402389
}
403390
}
404391

405392
findViewById(R.id.parse_progress).setVisibility(View.GONE);
406393

407394
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+
}
414407
}
408+
if (itemsBuilder.length() > 0) {
409+
return itemsBuilder.toString();
410+
}
411+
return null;
415412
}
416413

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+
417500
private void sendOrder() {
418501
try {
419502
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",

app/src/main/java/ac/robinson/ticqr/TickBoxImageParserTask.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ protected ArrayList<PointF> doInBackground(Void... unused) {
6161

6262
// we look for *un-ticked* boxes, rather than ticked, as they are uniform in appearance (and hence easier to
6363
// detect) - they show up as a box within a box
64-
ArrayList<PointF> centrePoints = new ArrayList<PointF>();
64+
ArrayList<PointF> centrePoints = new ArrayList<>();
6565
int minimumOuterBoxArea = (int) Math.round(Math.pow(mBoxSize, 2));
6666
int maximumOuterBoxArea = (int) Math.round(Math.pow(mBoxSize * 1.35f, 2));
6767
int minimumInnerBoxArea = (int) Math.round(Math.pow(mBoxSize * 0.5f, 2));
@@ -99,15 +99,15 @@ protected ArrayList<PointF> doInBackground(Void... unused) {
9999

100100
// get the contours in the image, and their hierarchy
101101
Mat hierarchyMat = new Mat();
102-
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
102+
List<MatOfPoint> contours = new ArrayList<>();
103103
Imgproc.findContours(bitMat, contours, hierarchyMat, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
104104
if (DEBUG) {
105105
Imgproc.drawContours(bitMat, contours, -1, new Scalar(30, 255, 255), 1);
106106
}
107107

108108
// parse the contours and look for a box containing another box, with similar enough sizes
109109
int numContours = contours.size();
110-
ArrayList<Integer> searchedContours = new ArrayList<Integer>();
110+
ArrayList<Integer> searchedContours = new ArrayList<>();
111111
Log.d(TAG, "Found " + numContours + " possible tick box areas");
112112
if (numContours > 0 && !hierarchyMat.empty()) {
113113
for (int i = 0; i < numContours; i++) {
@@ -312,7 +312,7 @@ protected ArrayList<PointF> doInBackground(Void... unused) {
312312
}
313313

314314
private void drawPoints(Mat bitMat, MatOfPoint boxPoints, Scalar colour, int width) {
315-
List<MatOfPoint> simplifiedOuterBox = new ArrayList<MatOfPoint>();
315+
List<MatOfPoint> simplifiedOuterBox = new ArrayList<>();
316316
simplifiedOuterBox.add(boxPoints);
317317
Imgproc.drawContours(bitMat, simplifiedOuterBox, -1, colour, width);
318318
}

0 commit comments

Comments
 (0)