在带有AppBarLayout的CoordinatorLayout中滚动时显示/隐藏BottomNavigationView

14

我试图在一个单独的CoordinatorLayout中同时使用AppBarLayoutBottomNavigationLayout,但我在隐藏BottomNavigationLayout方面遇到了困难,这是符合Material Design指南的要求。

我的意思是像这样:

<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个回答

23

经过一两天的搜索,我最终选择使用自定义的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年4月):有关onStartNestedScrollonNestedPreScroll及其新版本的细微澄清,请参见评论部分。

1
谢谢!顺便说一句,onStartNestedScrollonNestedPreScroll现在已经过时了。两者都需要int type作为最后一个参数;-) - Jokus
1
https://android.jlelse.eu/scroll-your-bottom-navigation-view-away-with-10-lines-of-code-346f1ed40e9e - Debjit
@stan0 不是应用栏。我有一个在顶部的布局需要快速返回。 - Debjit
1
支持库中具有一个集成的 hide_bottom_view_on_scroll_behavior 执行相同操作。 - Softlion
这不是Material。你正在使用支持库。 - kelalaka
显示剩余3条评论

5

您还可以使用HideBottomViewOnScrollBehavior。这种行为基本上以相同的方式工作,但还处理取消正在运行的任何现有动画,这应该更有利于性能。


看起来很有前途!这可能是现在正确的做法,但不幸的是我现在没有时间测试它。所以我希望其他用户能够测试并投赞成票,以改进这个问题/答案。 - stan0
你现在测试过了吗?如果是的话,能否告诉我如何使用它? - manish poddar
看一下源代码,它非常简单。https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/behavior/HideBottomViewOnScrollBehavior.java - Cameron Ketcham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接