如何实现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
相关产品推荐
相关产品推荐

