在 Android 中为 BottomAppBar 实施 app:hideOnScroll

Implementing app:hideOnScroll for BottomAppBar in Android

我有一个应用 Activity,许多片段模型,其中几个片段有一个 RecyclerView 来显示包含内容的卡片。我还从 Material Design 2.0 实现了 BottomAppBar,一切都很好,除非 AppBar 阻塞了 RecyclerView 中的最后一个 CardView。

在布局方面,我在 Fragment 中的 ConstraintLayout 中有一个 RecyclerView,它位于主要 activity 的 FrameLayout 中。

文档显示,要在 Scroll 上隐藏 BottomAppBar,we need to implement RecyclerView inside a NestedScrollView. There is one question here on SO where the answer has stated the same as well, but there seems to be no actual documentation or examples to demonstrate how this is to be done, except for this article on Medium,它直接使用 Activity 中的 NestedScrollView,持有 CoordinatorLayout,后者持有 ConstraintLayout。

注意:我认为它也适用于魔术,因为在我的片段中复制布局在我的应用程序中根本没有任何效果。

这里如何使用 NestedScrollView?

PS : 我需要有 TextView,因为我将 RecyclerView 设置为 VISIBILITY.GONE 并在没有数据可显示时将 TextView 设置为 VISIBLE。

片段布局

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="in.domain.APPNAME.Fragments.FragmentList">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewIncident"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingBottom="30dp"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <TextView
        android:id="@+id/emptyView"
        android:layout_width="wrap_content"
        android:layout_height="17dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="No Incidents to display"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.503"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Activity布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/uberLayout"
    tools:context=".APPNAME">

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:id="@+id/containerFrameLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </FrameLayout>

    </android.support.constraint.ConstraintLayout>

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <android.support.design.bottomappbar.BottomAppBar
            android:id="@+id/bottom_app_bar"
            style="@style/Widget.MaterialComponents.BottomAppBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            app:backgroundTint="@color/colorPrimary"
            app:fabAlignmentMode="center"
            app:navigationIcon="@drawable/baseline_menu_white_24dp"
            app:hideOnScroll="true"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        </android.support.design.bottomappbar.BottomAppBar>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/floatingActionButton"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:clickable="true"
            android:src="@drawable/baseline_add_white_24dp"
            app:backgroundTint="@color/brightred"
            app:fabSize="normal"
            app:layout_anchor="@+id/bottom_app_bar"
            tools:layout_editor_absoluteX="160dp"
            tools:layout_editor_absoluteY="465dp" />


    </android.support.design.widget.CoordinatorLayout>

</android.support.design.widget.CoordinatorLayout>

您不应该将 BottomAppBarFloatingActionButton 放在单独的 CoordinatorLayout 中。放弃他们所在的 CoordinatorLayoutFrameLayout 周围的 ConstraintLayout,这可能已经解决了问题。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/uberLayout"
    tools:context=".APPNAME">

    <FrameLayout
        android:id="@+id/containerFrameLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

    <android.support.design.bottomappbar.BottomAppBar
        android:id="@+id/bottom_app_bar"
        style="@style/Widget.MaterialComponents.BottomAppBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:backgroundTint="@color/colorPrimary"
        app:fabAlignmentMode="center"
        app:navigationIcon="@drawable/baseline_menu_white_24dp"
        app:hideOnScroll="true"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:src="@drawable/baseline_add_white_24dp"
        app:backgroundTint="@color/brightred"
        app:fabSize="normal"
        app:layout_anchor="@+id/bottom_app_bar" />

</android.support.design.widget.CoordinatorLayout>

我使用的是类似的布局,唯一的区别是 <fragment> 而不是 <FrameLayout>,并且 BottomAppBar 在滚动时隐藏得很好。如果我们的滚动内容是 RecyclerView,我们就不需要使用 NestedScrollView,因为 RecyclerView 实现了 NestedScrollingChild.

This interface should be implemented by View subclasses that wish to support dispatching nested scrolling operations to a cooperating parent ViewGroup.