From f8943af4024744b641ae9cd98d3337876c64ad0a Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Sun, 19 Jan 2020 16:45:17 +0100 Subject: [PATCH 1/5] Tap barcode to align to top --- .../card_locker/LoyaltyCardViewActivity.java | 101 +++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java index 50712e423..30e3af167 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java @@ -7,6 +7,8 @@ import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; + +import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.graphics.ColorUtils; import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.widget.TextViewCompat; @@ -19,6 +21,7 @@ import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; @@ -49,7 +52,12 @@ public class LoyaltyCardViewActivity extends AppCompatActivity ImportURIHelper importURIHelper; Settings settings; + String cardIdString; + BarcodeFormat format; + boolean backgroundNeedsDarkIcons; + boolean barcodeIsFullscreen = false; + ViewGroup.LayoutParams barcodeImageState; private void extractIntentFields(Intent intent) { @@ -104,6 +112,21 @@ public class LoyaltyCardViewActivity extends AppCompatActivity collapsingToolbarLayout = findViewById(R.id.collapsingToolbarLayout); rotationEnabled = true; + + // Allow making barcode fullscreen on tap + barcodeImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if(barcodeIsFullscreen) + { + setBarcodeFullscreen(false); + } + else + { + setBarcodeFullscreen(true); + } + } + }); } @Override @@ -143,8 +166,8 @@ public class LoyaltyCardViewActivity extends AppCompatActivity } String formatString = loyaltyCard.barcodeType; - final BarcodeFormat format = !formatString.isEmpty() ? BarcodeFormat.valueOf(formatString) : null; - final String cardIdString = loyaltyCard.cardId; + format = !formatString.isEmpty() ? BarcodeFormat.valueOf(formatString) : null; + cardIdString = loyaltyCard.cardId; cardIdFieldView.setText(loyaltyCard.cardId); TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(cardIdFieldView, @@ -244,6 +267,18 @@ public class LoyaltyCardViewActivity extends AppCompatActivity } } + @Override + public void onBackPressed() { + if (barcodeIsFullscreen) + { + setBarcodeFullscreen(false); + return; + } + + super.onBackPressed(); + return; + } + @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -321,4 +356,66 @@ public class LoyaltyCardViewActivity extends AppCompatActivity setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); } } + + private void setBarcodeFullscreen(boolean enabled) + { + ActionBar actionBar = getSupportActionBar(); + if(enabled && !barcodeIsFullscreen) + { + // Save previous barcodeImage state + barcodeImageState = barcodeImage.getLayoutParams(); + + // Hide actionbar + if(actionBar != null) + { + actionBar.hide(); + } + + // Hide collapsingToolbar + collapsingToolbarLayout.setVisibility(View.GONE); + + // Set Android to fullscreen mode + getWindow().getDecorView().setSystemUiVisibility( + getWindow().getDecorView().getSystemUiVisibility() + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_FULLSCREEN + ); + + // Make barcode take all space + barcodeImage.setLayoutParams(new ConstraintLayout.LayoutParams( + ConstraintLayout.LayoutParams.MATCH_PARENT, + ConstraintLayout.LayoutParams.MATCH_PARENT + )); + + // Move barcode to top + barcodeImage.setScaleType(ImageView.ScaleType.FIT_START); + + // Set current state + barcodeIsFullscreen = true; + } + else if(!enabled && barcodeIsFullscreen) + { + // Show actionbar + if(actionBar != null) + { + actionBar.show(); + } + + // Show collapsingToolbar + collapsingToolbarLayout.setVisibility(View.VISIBLE); + + // Unset fullscreen mode + getWindow().getDecorView().setSystemUiVisibility( + getWindow().getDecorView().getSystemUiVisibility() + & ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + & ~View.SYSTEM_UI_FLAG_FULLSCREEN + ); + + // Turn barcode back to normal + barcodeImage.setLayoutParams(barcodeImageState); + + // Set current state + barcodeIsFullscreen = false; + } + } } From 2c12c312e3b28f31bc680e937d4adb97ccb99cc4 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Sun, 19 Jan 2020 17:46:50 +0100 Subject: [PATCH 2/5] Add unit tests --- .../LoyaltyCardViewActivityTest.java | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java index e139de488..4c45e3cca 100644 --- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java +++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java @@ -1,6 +1,7 @@ package protect.card_locker; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.robolectric.Shadows.shadowOf; @@ -22,6 +23,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; +import android.widget.ImageView; import android.widget.TextView; import androidx.core.widget.TextViewCompat; import com.google.zxing.BarcodeFormat; @@ -35,7 +37,6 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.shadows.ShadowActivity; import org.robolectric.shadows.ShadowLog; @@ -686,6 +687,69 @@ public class LoyaltyCardViewActivityTest } } + @Test + public void checkBarcodeFullscreenWorkflow() + { + ActivityController activityController = createActivityWithLoyaltyCard(false); + + Activity activity = (Activity)activityController.get(); + DBHelper db = new DBHelper(activity); + db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE, Color.BLACK, Color.WHITE); + + activityController.start(); + activityController.visible(); + activityController.resume(); + + assertEquals(false, activity.isFinishing()); + + ImageView barcodeImage = activity.findViewById(R.id.barcode); + View collapsingToolbarLayout = activity.findViewById(R.id.collapsingToolbarLayout); + + // Android should not be in fullscreen mode + int uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + + // Elements should be visible + assertEquals(View.VISIBLE, collapsingToolbarLayout.getVisibility()); + + // Click barcode to toggle fullscreen + barcodeImage.performClick(); + + // Android should be in fullscreen mode + uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + + // Elements should not be visible + assertEquals(View.GONE, collapsingToolbarLayout.getVisibility()); + + // Clicking barcode again should deactivate fullscreen mode + barcodeImage.performClick(); + uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + assertEquals(View.VISIBLE, collapsingToolbarLayout.getVisibility()); + + // Another click back to fullscreen + barcodeImage.performClick(); + uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + assertEquals(View.GONE, collapsingToolbarLayout.getVisibility()); + + // In full screen mode, back button should disable fullscreen + activity.onBackPressed(); + uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + assertEquals(View.VISIBLE, collapsingToolbarLayout.getVisibility()); + + // Pressing back when not in full screen should finish activity + activity.onBackPressed(); + assertEquals(true, activity.isFinishing()); + } + @Test public void importCard() { From 4a7e8b6ebab870e079be0ab644f9688ac9a8a5bc Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Sun, 19 Jan 2020 19:07:06 +0100 Subject: [PATCH 3/5] Reset state on paused to prevent layout glitches --- .../card_locker/LoyaltyCardViewActivity.java | 6 ++++++ .../card_locker/LoyaltyCardViewActivityTest.java | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java index 30e3af167..edeaf63b9 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java @@ -145,6 +145,12 @@ public class LoyaltyCardViewActivity extends AppCompatActivity Log.i(TAG, "To view card: " + loyaltyCardId); + if(barcodeIsFullscreen) + { + // Properly reset state to prevent any issues + recreate(); + } + // The brightness value is on a scale from [0, ..., 1], where // '1' is the brightest. We attempt to maximize the brightness // to help barcode readers scan the barcode. diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java index 4c45e3cca..230870f34 100644 --- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java +++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java @@ -738,6 +738,21 @@ public class LoyaltyCardViewActivityTest assertEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); assertEquals(View.GONE, collapsingToolbarLayout.getVisibility()); + // Resuming the activity should revert the state to normal view + activityController.pause(); + activityController.resume(); + uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + assertEquals(View.VISIBLE, collapsingToolbarLayout.getVisibility()); + + // Clicking the barcode should still work to fullscreen again + barcodeImage.performClick(); + uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); + assertEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); + assertEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); + assertEquals(View.GONE, collapsingToolbarLayout.getVisibility()); + // In full screen mode, back button should disable fullscreen activity.onBackPressed(); uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); From 3600065ef8fde538dd994b8ab26b50dbc21c2006 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Sun, 19 Jan 2020 19:55:08 +0100 Subject: [PATCH 4/5] Robolectric crashes if activity recreates --- .../card_locker/LoyaltyCardViewActivityTest.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java index 230870f34..4c45e3cca 100644 --- a/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java +++ b/app/src/test/java/protect/card_locker/LoyaltyCardViewActivityTest.java @@ -738,21 +738,6 @@ public class LoyaltyCardViewActivityTest assertEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); assertEquals(View.GONE, collapsingToolbarLayout.getVisibility()); - // Resuming the activity should revert the state to normal view - activityController.pause(); - activityController.resume(); - uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); - assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); - assertNotEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); - assertEquals(View.VISIBLE, collapsingToolbarLayout.getVisibility()); - - // Clicking the barcode should still work to fullscreen again - barcodeImage.performClick(); - uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); - assertEquals(uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY, uiOptions); - assertEquals(uiOptions | View.SYSTEM_UI_FLAG_FULLSCREEN, uiOptions); - assertEquals(View.GONE, collapsingToolbarLayout.getVisibility()); - // In full screen mode, back button should disable fullscreen activity.onBackPressed(); uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility(); From fd6c66a86a730335158468c27b24319d6c578daa Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Tue, 21 Jan 2020 20:06:58 +0100 Subject: [PATCH 5/5] Improve documentation --- .../card_locker/LoyaltyCardViewActivity.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java index edeaf63b9..f91014d68 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java @@ -119,11 +119,11 @@ public class LoyaltyCardViewActivity extends AppCompatActivity public void onClick(View view) { if(barcodeIsFullscreen) { - setBarcodeFullscreen(false); + setFullscreen(false); } else { - setBarcodeFullscreen(true); + setFullscreen(true); } } }); @@ -147,7 +147,10 @@ public class LoyaltyCardViewActivity extends AppCompatActivity if(barcodeIsFullscreen) { - // Properly reset state to prevent any issues + // Completely reset state + // + // This prevents the barcode from taking up the entire screen + // on resume and thus being stretched out of proportion. recreate(); } @@ -277,7 +280,7 @@ public class LoyaltyCardViewActivity extends AppCompatActivity public void onBackPressed() { if (barcodeIsFullscreen) { - setBarcodeFullscreen(false); + setFullscreen(false); return; } @@ -363,10 +366,16 @@ public class LoyaltyCardViewActivity extends AppCompatActivity } } - private void setBarcodeFullscreen(boolean enabled) + /** + * When enabled, hides the status bar and moves the barcode to the top of the screen. + * + * The purpose of this function is to make sure the barcode can be scanned from the phone + * by machines which offer no space to insert the complete device. + */ + private void setFullscreen(boolean enable) { ActionBar actionBar = getSupportActionBar(); - if(enabled && !barcodeIsFullscreen) + if(enable && !barcodeIsFullscreen) { // Save previous barcodeImage state barcodeImageState = barcodeImage.getLayoutParams(); @@ -399,7 +408,7 @@ public class LoyaltyCardViewActivity extends AppCompatActivity // Set current state barcodeIsFullscreen = true; } - else if(!enabled && barcodeIsFullscreen) + else if(!enable && barcodeIsFullscreen) { // Show actionbar if(actionBar != null)