You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义BottomNavigationViewBehavior时onNestedScroll未触发,需实现滚动隐藏

实现BottomNavigationView随滚动隐藏的方案

哈哈,这个需求我前段时间刚折腾过!Android框架确实没有开箱即用的方案,但借助CoordinatorLayout的Behavior机制,我们自己写几行代码就能完美实现。下面给你一步步拆解:

1. 调整布局结构

首先确保你的布局根节点是CoordinatorLayout,并且给BottomNavigationView绑定自定义Behavior。完整布局示例如下:

<androidx.coordinatorlayout.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 你的滚动内容容器,比如RecyclerView/NestedScrollView -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

    <!-- 底部导航栏,绑定自定义Behavior -->
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        app:menu="@menu/your_bottom_menu"
        app:layout_behavior=".BottomNavHideBehavior"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

注意:如果还在用旧的support包,把androidx替换成android.support即可,但更建议迁移到AndroidX。

2. 编写自定义Behavior类

这个类是核心,用来监听滚动事件,控制BottomNavigationView的显示/隐藏:

Java版本

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.core.view.ViewCompat;

public class BottomNavHideBehavior extends CoordinatorLayout.Behavior<BottomNavigationView> {

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

    // 只监听垂直方向的滚动
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View directTargetChild, View target, int axes, int type) {
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }

    // 根据滚动方向处理导航栏的显示隐藏
    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, BottomNavigationView child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, int[] consumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed);
        
        // 向上滚动:隐藏导航栏(translationY设为自身高度,移出屏幕)
        if (dyConsumed > 0 && child.getTranslationY() < child.getHeight()) {
            child.animate().translationY(child.getHeight()).setDuration(200).start();
        } 
        // 向下滚动:显示导航栏(translationY设为0,回到原位)
        else if (dyConsumed < 0 && child.getTranslationY() > 0) {
            child.animate().translationY(0).setDuration(200).start();
        }
    }
}

Kotlin版本

import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.core.view.ViewCompat

class BottomNavHideBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<BottomNavigationView>(context, attrs) {

    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: BottomNavigationView,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int
    ): Boolean {
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL
    }

    override fun onNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: BottomNavigationView,
        target: View,
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        type: Int,
        consumed: IntArray
    ) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed)
        
        when {
            // 向上滚动隐藏
            dyConsumed > 0 && child.translationY < child.height -> {
                child.animate().translationY(child.height.toFloat()).setDuration(200).start()
            }
            // 向下滚动显示
            dyConsumed < 0 && child.translationY > 0 -> {
                child.animate().translationY(0f).setDuration(200).start()
            }
        }
    }
}

3. 注意事项

  • 你的滚动容器(RecyclerView/NestedScrollView)必须支持嵌套滚动,这两个控件默认已经支持,如果是自定义滚动View,需要实现NestedScrollingChild接口。
  • 动画时长可以根据需求调整,200ms是比较自然的过渡速度,你可以改成其他数值。
  • 确保依赖了Material组件库,不然BottomNavigationView会找不到:
implementation 'com.google.android.material:material:1.9.0'

内容的提问来源于stack exchange,提问作者eight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:38:18