commit facced454fa740c56bda0c8666e6984009bae4f2 parent a38a0dffe2b6d9803d1f8109d46033f608da0113 Author: Mugurell <Mugurell@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:35:16 +0000 Bug 2005988 - Consider toolbars almost fully hidden as fully hidden for EngineView clipping r=android-reviewers,moyin When calculating the vertical clipping for the EngineView the toolbars might be off by 1 pixels from being fully hidden. This change will treat toolbars as fully hidden if their position is within a small pixel threshold of being completely off-screen, ensuring the EngineView is clipped correctly in these edge cases. Differential Revision: https://phabricator.services.mozilla.com/D277109 Diffstat:
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehavior.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehavior.kt @@ -12,6 +12,8 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout import mozilla.components.concept.engine.EngineView import mozilla.components.concept.toolbar.ScrollableToolbar import mozilla.components.support.ktx.android.view.findViewInHierarchy +import kotlin.let +import kotlin.math.abs import kotlin.math.roundToInt /** @@ -52,6 +54,7 @@ class EngineViewClippingBehavior( set(value) { field = value.coerceIn(-topToolbarHeight.toFloat(), 0f) } private val hasTopToolbar = topToolbarHeight > 0 + private val dynamicToolbarMaxHeight = topToolbarHeight + bottomToolbarHeight override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean { if (dependency is ScrollableToolbar) { @@ -103,8 +106,14 @@ class EngineViewClippingBehavior( // is either positive or zero, but for clipping // the values should be negative because the baseline // for clipping is bottom toolbar height. - val contentBottomClipping = recentTopToolbarTranslation - recentBottomToolbarTranslation - it.setVerticalClipping(contentBottomClipping.roundToInt()) + val contentBottomClipping = (recentTopToolbarTranslation - recentBottomToolbarTranslation).roundToInt() + val safeVerticalClipping = when { + // Consider toolbars almost fully hidden as fully hidden. + // See bug 2005988 for context. + abs(dynamicToolbarMaxHeight + contentBottomClipping) in 0..2 -> -dynamicToolbarMaxHeight + else -> contentBottomClipping + } + it.setVerticalClipping(safeVerticalClipping) } } } diff --git a/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehaviorTest.kt b/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehaviorTest.kt @@ -25,6 +25,7 @@ import org.junit.runner.RunWith import org.mockito.Mockito.doReturn import org.mockito.Mockito.spy import org.mockito.Mockito.verify +import kotlin.math.roundToInt @RunWith(AndroidJUnit4::class) class EngineViewClippingBehaviorTest { @@ -237,6 +238,23 @@ class EngineViewClippingBehaviorTest { } @Test + fun `GIVEN a top toolbar almost fully hidden THEN configure the engine view with a fully hidden toolbar`() { + doReturn(TOOLBAR_PARENT_HEIGHT).`when`(coordinatorLayout).height + doReturn(TOOLBAR_TOP_WHEN_POSITIONED_AT_TOP).`when`(toolbar).top + doReturn(TOOLBAR_TOP_WHEN_POSITIONED_AT_BOTTOM).`when`(toolbarContainerView).top + doReturn(-(TOOLBAR_HEIGHT + 1)).`when`(toolbar).translationY + + buildEngineViewClipping2Behavior( + topToolbarHeight = TOOLBAR_HEIGHT.toInt(), + bottomToolbarHeight = 0, + ).run { + applyUpdatesDependentViewChanged(coordinatorLayout, toolbar) + } + + verify(engineView).setVerticalClipping(-TOOLBAR_HEIGHT.roundToInt()) + } + + @Test fun `GIVEN a bottom toolbar WHEN translation returns NaN THEN no exception thrown`() { doReturn(100).`when`(toolbar).height doReturn(Float.NaN).`when`(toolbar).translationY