From 5f7309426f803602ccecbf572df8236ff6ced12c Mon Sep 17 00:00:00 2001 From: gitstart Date: Fri, 10 Feb 2023 07:03:57 +0000 Subject: [PATCH] Bug 1812144 - Homescreen is scrollable even if there is no content --- .../org/mozilla/fenix/home/HomeFragment.kt | 12 ++++ .../AppBarLayoutBehaviorEmptyRecyclerView.kt | 58 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 app/src/main/java/org/mozilla/fenix/utils/AppBarLayoutBehaviorEmptyRecyclerView.kt diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 7a2f37f11bc2..cbaa66bba8f0 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -126,6 +126,7 @@ import org.mozilla.fenix.perf.MarkersFragmentLifecycleCallbacks import org.mozilla.fenix.perf.runBlockingIncrement import org.mozilla.fenix.search.toolbar.SearchSelectorMenu import org.mozilla.fenix.tabstray.TabsTrayAccessPoint +import org.mozilla.fenix.utils.AppBarLayoutBehaviorEmptyRecyclerView import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD import org.mozilla.fenix.utils.ToolbarPopupWindow import org.mozilla.fenix.utils.allowUndo @@ -503,6 +504,15 @@ class HomeFragment : Fragment() { } } + private fun appBarScrollingBehaviorWhenEmptyData() { + val appbarLayoutParams = binding.homeAppBar.layoutParams + if (appbarLayoutParams is CoordinatorLayout.LayoutParams) { + val behavior = AppBarLayoutBehaviorEmptyRecyclerView() + appbarLayoutParams.behavior = behavior + } + binding.homeAppBar.setExpanded(true, true) + } + private fun updateLayout(view: View) { when (requireContext().settings().toolbarPosition) { ToolbarPosition.TOP -> { @@ -640,6 +650,8 @@ class HomeFragment : Fragment() { } } + appBarScrollingBehaviorWhenEmptyData() + // DO NOT MOVE ANYTHING BELOW THIS addMarker CALL! requireComponents.core.engine.profiler?.addMarker( MarkersFragmentLifecycleCallbacks.MARKER_NAME, diff --git a/app/src/main/java/org/mozilla/fenix/utils/AppBarLayoutBehaviorEmptyRecyclerView.kt b/app/src/main/java/org/mozilla/fenix/utils/AppBarLayoutBehaviorEmptyRecyclerView.kt new file mode 100644 index 000000000000..e9f9bc48d1b5 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/utils/AppBarLayoutBehaviorEmptyRecyclerView.kt @@ -0,0 +1,58 @@ +package org.mozilla.fenix.utils + +import android.view.MotionEvent +import android.view.View +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.appbar.AppBarLayout + +/** + * This class is a workaround for the issue described in [https://bugzilla.mozilla.org/show_bug.cgi?id=1812144] + * It is used to prevent the app bar from collapsing when the recycler view is empty. + */ +@Suppress("MaxLineLength") +class AppBarLayoutBehaviorEmptyRecyclerView : AppBarLayout.Behavior() { + private var isRecyclerViewScrollable = false + + override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: AppBarLayout, ev: MotionEvent): Boolean { + return isRecyclerViewScrollable && super.onInterceptTouchEvent(parent, child, ev) + } + + override fun onStartNestedScroll( + parent: CoordinatorLayout, + child: AppBarLayout, + directTargetChild: View, + target: View, + nestedScrollAxes: Int, + type: Int, + ): Boolean { + updateScrollableState(target) + return isRecyclerViewScrollable && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type) + } + + override fun onNestedFling( + coordinatorLayout: CoordinatorLayout, + child: AppBarLayout, + target: View, + velocityX: Float, + velocityY: Float, + consumed: Boolean, + ): Boolean { + updateScrollableState(target) + return isRecyclerViewScrollable && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed) + } + + /** + * If the child is a [RecyclerView], check if it is scrollable. Otherwise, assume it is scrollable. + * This is a workaround because the RecyclerView is having itemCount 2 when all items are disabled, + * so we are checking that instead 0 count. + */ + private fun updateScrollableState(child: View) { + isRecyclerViewScrollable = if (child is RecyclerView) { + val rvAdapter = child.adapter + rvAdapter != null && rvAdapter.itemCount > 2 + } else { + true + } + } +}