Показать / скрыть BottomNavigationView при прокрутке в CoordinatorLayout с помощью AppBarLayout

Я пытаюсь использовать оба AppBarLayout а также BottomNavigationLayout в одном CoordinatorLayout и у меня возникают трудности с сокрытием BottomNavigationLayout в соответствии с требованиями материалов.

Я имею в виду что-то вроде этого:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="false">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_insetEdge="top"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:layout_scrollFlags="scroll|enterAlways"/>
    </android.support.design.widget.AppBarLayout>


    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_nav"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_gravity="bottom"
        app:menu="@menu/menu_bottom_navigation"/>

    <FrameLayout
        android:id="@+id/content_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

Как видите, у меня тоже есть FrameLayout это используется, чтобы содержать фрагмент с фактическим содержанием. В настоящее время не существует встроенного поведения по умолчанию для BottomNavigationView - ни для самого взгляда, ни для его родных братьев. Существующий appbar_scrolling_view_behavior обрабатывает представление содержимого в координации с панелью приложения, но игнорирует других братьев и сестер.

Я ищу решение, чтобы скрыть и показать как панель приложения, так и нижнюю навигационную панель при прокрутке.

2 ответа

Решение

После дня или двух поисков я поселился с обычаем Behavior прикреплен к BottomNavigationView, Его основная идея состоит в том, чтобы определить, когда прокручивается одноуровневый элемент BottomNavigationView, чтобы он мог скрыть BottomNavigationView. Что-то вроде этого:

public class BottomNavigationBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {

    public BottomNavigationBehavior() {
        super();
    }

    public BottomNavigationBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, BottomNavigationView child, View dependency) {
        boolean dependsOn = dependency instanceof FrameLayout;
        return dependsOn;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View directTargetChild, View target, int nestedScrollAxes) {
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target, int dx, int dy, int[] consumed) {
        if(dy < 0) {
            showBottomNavigationView(child);
        }
        else if(dy > 0) {
            hideBottomNavigationView(child);
        }
    }

    private void hideBottomNavigationView(BottomNavigationView view) {
        view.animate().translationY(view.getHeight());
    }

    private void showBottomNavigationView(BottomNavigationView view) {
        view.animate().translationY(0);
    }
}

Как видите, я использую простой ViewPropertyAnimator, полученные с использованием дочерних представлений animate метод. Это приводит к простой анимации, которая на самом деле не соответствует AppBarLayout поведение, но оно достаточно прилично, чтобы хорошо выглядеть, и в то же время достаточно просто для реализации.

Я ожидаю, что в какой-то момент команда Android добавит стандартное поведение для BottomNavigationView в библиотеку поддержки, поэтому я не думаю, что разумно тратить гораздо больше времени на точное дублирование поведения AppBarLayout.

редактировать (апрель 2018 г.): см. раздел с комментариями для небольшого разъяснения о onStartNestedScroll а также onNestedPreScroll и их новые версии.

Вы также можете использовать HideBottomViewOnScrollBehavior. Это поведение работает в основном таким же образом, но также обрабатывает отмену любых существующих анимаций, которые работают, что должно быть лучше для производительности.

Другие вопросы по тегам