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

如何实现RecyclerView滑到末尾时BottomNavigationBar跟随最后一项上滑

实现方案

首先你原有代码存在两个核心问题:一是缺失endOfList成员变量定义,二是滚动逻辑没有针对列表到底的场景做特殊处理,以下是调整后的完整代码:

public class NavigationBehavior extends CoordinatorLayout.Behavior<View> {
    private float height = 0;
    // 补全列表是否到底的状态变量
    private boolean endOfList = false;
    // 动画时长,可自行调整
    private static final int ANIM_DURATION = 200;

    public NavigationBehavior() {
    }

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

    @Override
    public boolean onLayoutChild(@NonNull CoordinatorLayout parent, @NonNull View child, int layoutDirection) {
        ViewGroup.MarginLayoutParams paramsCompat =
                (ViewGroup.MarginLayoutParams) child.getLayoutParams();
        height = child.getMeasuredHeight() + paramsCompat.bottomMargin;
        return super.onLayoutChild(parent, child, layoutDirection);
    }

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

    @Override
    public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
        // 如果已经滑动到列表末尾,强制显示导航栏,不处理滚动隐藏逻辑
        if (endOfList) {
            animateNavToShow(child);
            return;
        }
        // 原有滚动逻辑,dy>0为向上滚动(内容上移)隐藏导航,dy<0为向下滚动显示导航
        float targetTranslationY = Float.max(0f, Float.min(height, child.getTranslationY() + dy));
        // 避免重复设置相同值
        if (child.getTranslationY() != targetTranslationY) {
            child.setTranslationY(targetTranslationY);
        }
    }

    public void setEndOfList(boolean endOfList) {
        this.endOfList = endOfList;
    }

    // 导航栏平滑显示的动画
    private void animateNavToShow(View child) {
        if (child.getTranslationY() == 0f) {
            return;
        }
        ViewCompat.animate(child)
                .translationY(0f)
                .setDuration(ANIM_DURATION)
                .setInterpolator(new DecelerateInterpolator())
                .start();
    }
}

配套使用步骤

你需要给绑定的RecyclerView添加滚动监听,实时判断是否滑动到列表底部,同步状态给Behavior:

// 初始化时获取导航栏的Behavior实例
BottomNavigationView navView = findViewById(R.id.nav_view);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) navView.getLayoutParams();
NavigationBehavior behavior = (NavigationBehavior) params.getBehavior();

// 给RecyclerView添加滚动监听
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        boolean isEnd = !recyclerView.canScrollVertically(1);
        if (behavior != null) {
            behavior.setEndOfList(isEnd);
            // 如果滑动到底部,直接触发显示
            if (isEnd) {
                navView.setTranslationY(0f);
            }
        }
    }
});

注意事项

  • 原有代码中无意义的public final void BottomNavigationBehavior()方法已删除,该方法不属于正确的构造方法定义,会导致逻辑异常
  • 若不需要平滑动画,可直接删除animateNavToShow方法,在需要显示的位置直接调用child.setTranslationY(0f)即可
  • 若存在分页加载场景,分页加载完成后如果还有下一页数据,需要手动调用setEndOfList(false)重置状态

内容的提问来源于stack exchange,提问作者Dušan Mičuda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 10:51:03