From 9c9843a38441654dd40389d303edbb56e567413e Mon Sep 17 00:00:00 2001 From: Matt Silber Date: Fri, 15 Dec 2023 16:26:28 -0500 Subject: [PATCH] Fixes #19 by adding an alternative method to perform a last-ditch post of the runnable when the view size is stil zero --- .../scratchoff/test/MainActivity.kt | 1 + .../scratchoff/ScratchableLayoutDrawer.java | 34 ++++++++++++++----- .../scratchoff/ScratchoffController.java | 18 +++++++++- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/scratchoff-sample/src/main/java/com/jackpocket/scratchoff/test/MainActivity.kt b/scratchoff-sample/src/main/java/com/jackpocket/scratchoff/test/MainActivity.kt index 97bbc11..7663dca 100644 --- a/scratchoff-sample/src/main/java/com/jackpocket/scratchoff/test/MainActivity.kt +++ b/scratchoff-sample/src/main/java/com/jackpocket/scratchoff/test/MainActivity.kt @@ -32,6 +32,7 @@ class MainActivity: AppCompatActivity(), ScratchoffController.ThresholdChangedLi .setClearAnimationDuration(1, TimeUnit.SECONDS) .setClearAnimationInterpolator(LinearInterpolator()) .setUsePreDrawForLayoutEnabled(true) + .setAttemptPostForIncompleteLayout(true) // .setTouchRadiusPx(25) // .setThresholdAccuracyQuality(Quality.LOW) // .setThresholdTargetRegionsProvider({ diff --git a/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchableLayoutDrawer.java b/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchableLayoutDrawer.java index 4a2d021..1160fa7 100644 --- a/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchableLayoutDrawer.java +++ b/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchableLayoutDrawer.java @@ -59,6 +59,7 @@ public interface Delegate { private Long activeClearTag = 0L; private boolean usePreDrawForLayoutEnabled = false; + private boolean attemptPostForIncompleteLayout = false; public ScratchableLayoutDrawer(Delegate delegate) { this.delegate = new WeakReference<>(delegate); @@ -354,10 +355,7 @@ private void deferRunnableUntilViewIsLaidOut(final View view, final Runnable run new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - if (runnable != null) { - runnable.run(); - } - + triggerOrPostRunnableOnLaidOut(view, runnable); view .getViewTreeObserver() @@ -375,10 +373,7 @@ public boolean onPreDraw() { new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - if (runnable != null) { - runnable.run(); - } - + triggerOrPostRunnableOnLaidOut(view, runnable); view .getViewTreeObserver() @@ -391,6 +386,22 @@ public void onGlobalLayout() { view.requestLayout(); } + private void triggerOrPostRunnableOnLaidOut(View view, Runnable runnable) { + if (runnable == null) { + return; + } + + if (attemptPostForIncompleteLayout) { + if (view.getWidth() < 1 || view.getHeight() < 1) { + view.post(runnable); + + return; + } + } + + runnable.run(); + } + @SuppressWarnings("WeakerAccess") public ScratchableLayoutDrawer setClearAnimationDurationMs(long clearAnimationDurationMs) { this.clearAnimationDurationMs = clearAnimationDurationMs; @@ -411,4 +422,11 @@ public ScratchableLayoutDrawer setUsePreDrawForLayoutEnabled(boolean usePreDrawF return this; } + + @SuppressWarnings("WeakerAccess") + public ScratchableLayoutDrawer setAttemptPostForIncompleteLayout(boolean attemptPostForIncompleteLayout) { + this.attemptPostForIncompleteLayout = attemptPostForIncompleteLayout; + + return this; + } } diff --git a/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchoffController.java b/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchoffController.java index b032088..7484b69 100644 --- a/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchoffController.java +++ b/scratchoff/src/main/java/com/jackpocket/scratchoff/ScratchoffController.java @@ -80,6 +80,7 @@ public interface ThresholdChangedListener { private boolean stateRestorationEnabled; private boolean usePreDrawForLayoutEnabled = false; + private boolean attemptPostForIncompleteLayout = false; /** * Create a new {@link ScratchoffController} instance targeting a scratchable layout. @@ -154,7 +155,8 @@ protected ScratchableLayoutDrawer createLayoutDrawer() { return new ScratchableLayoutDrawer(this) .setClearAnimationDurationMs(clearAnimationDurationMs) .setClearAnimationInterpolator(clearAnimationInterpolator) - .setUsePreDrawForLayoutEnabled(usePreDrawForLayoutEnabled); + .setUsePreDrawForLayoutEnabled(usePreDrawForLayoutEnabled) + .setAttemptPostForIncompleteLayout(attemptPostForIncompleteLayout); } protected ScratchoffThresholdProcessor createThresholdProcessor() { @@ -484,6 +486,20 @@ public ScratchoffController setUsePreDrawForLayoutEnabled(boolean usePreDrawForL return this; } + /** + * Set whether or not to attempt one final last-ditch {@link View#post} when determining the + * layout sizing of our {@link #layoutDrawer} if our {@link android.view.ViewTreeObserver} + * attempt ran while the {@link #scratchableLayout}'s width or height is still zero. + * This is in attempt to fix #19 caused by the width or height of the View being + * zero when attempting to create the scratchable {@link Bitmap} instances. + * The default for this value is false for the original (crashing) behavior. + */ + public ScratchoffController setAttemptPostForIncompleteLayout(boolean attemptPostForIncompleteLayout) { + this.attemptPostForIncompleteLayout = attemptPostForIncompleteLayout; + + return this; + } + public View getViewBehind() { return behindView.get(); }