diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/ui/fab/HideFabOnScrollBehavior.kt b/app/ui/legacy/src/main/java/com/fsck/k9/ui/fab/HideFabOnScrollBehavior.kt index c3ea873b9..7fb37295e 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/ui/fab/HideFabOnScrollBehavior.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/ui/fab/HideFabOnScrollBehavior.kt @@ -1,5 +1,6 @@ package com.fsck.k9.ui.fab +import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet import android.view.Gravity @@ -8,8 +9,17 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.marginBottom import com.google.android.material.behavior.HideBottomViewOnScrollBehavior import com.google.android.material.floatingactionbutton.FloatingActionButton +import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar.SnackbarLayout +/** + * Hides the floating action button when the `CoordinatorLayout` is scrolled. + * + * The behavior to hide the FAB when the [CoordinatorLayout] is scrolled is provided by the super class + * [HideBottomViewOnScrollBehavior]. The code in this class adjusts the vertical position of the FAB when a [Snackbar] + * is visible. This is necessary because we (like many others) deliberately ignore the + * [guideline](https://m3.material.io/components/snackbar/guidelines) to display a `Snackbar` above the FAB. + */ class HideFabOnScrollBehavior(context: Context, attributes: AttributeSet) : HideBottomViewOnScrollBehavior(context, attributes) { @@ -23,7 +33,7 @@ class HideFabOnScrollBehavior(context: Context, attributes: AttributeSet) : } override fun layoutDependsOn(parent: CoordinatorLayout, child: FloatingActionButton, dependency: View): Boolean { - return dependency is SnackbarLayout || super.layoutDependsOn(parent, child, dependency) + return dependency.isSnackbarLayout() || super.layoutDependsOn(parent, child, dependency) } override fun onDependentViewChanged( @@ -31,7 +41,7 @@ class HideFabOnScrollBehavior(context: Context, attributes: AttributeSet) : child: FloatingActionButton, dependency: View, ): Boolean { - if (dependency is SnackbarLayout) { + if (dependency.isSnackbarLayout()) { val additionalHiddenOffsetY = dependency.height + dependency.marginBottom setAdditionalHiddenOffsetY(child, additionalHiddenOffsetY) } @@ -42,8 +52,15 @@ class HideFabOnScrollBehavior(context: Context, attributes: AttributeSet) : override fun onDependentViewRemoved(parent: CoordinatorLayout, child: FloatingActionButton, dependency: View) { super.onDependentViewRemoved(parent, child, dependency) - if (dependency is SnackbarLayout) { + if (dependency.isSnackbarLayout()) { setAdditionalHiddenOffsetY(child, 0) } } + + // SnackbarLayout is a restricted type that shouldn't be accessed from outside of its library. However, there + // doesn't seem to be a public API we could use to implement the desired behavior. + @SuppressLint("RestrictedApi") + private fun View.isSnackbarLayout(): Boolean { + return this is SnackbarLayout + } } diff --git a/config/lint/lint.xml b/config/lint/lint.xml index 45f78ab1e..71b882c6d 100644 --- a/config/lint/lint.xml +++ b/config/lint/lint.xml @@ -1,6 +1,7 @@ +