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

BottomSheetBehavior中RecyclerView无法完全向下滚动如何解决?

问题分析

当BottomSheet处于半展开(peekHeight对应状态)时,RecyclerView无法滚动到底部的核心原因有两点:

  1. RecyclerView配置了app:layout_behavior="@string/appbar_scrolling_view_behavior",这个Behavior是为配合AppBarLayout滚动设计的,在BottomSheet场景中会干扰RecyclerView的布局测量与滚动范围计算。
  2. BottomSheet半展开时,实际显示高度被限制为peekHeight,但RecyclerView仍按父布局总高度(450dp)计算自身高度,导致部分列表项被BottomSheet的可视区域裁剪,无法滚动到。
解决方案

步骤1:移除RecyclerView的冗余Behavior

修改activity_test_sheet.xml中的RecyclerView配置,删除冲突的Behavior:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:nestedScrollingEnabled="true"
    android:overScrollMode="never"
    android:scrollbars="none"/>

步骤2:监听BottomSheet状态,动态调整RecyclerView高度

在Activity中添加BottomSheet状态监听器,根据当前状态计算RecyclerView的可用高度,确保滚动范围与BottomSheet可视区域匹配:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    recyclerView = findViewById(R.id.recyclerView);
    bottomSheetLayout = findViewById(R.id.bottomSheetLayout);
    sheetBehavior = BottomSheetBehavior.from(bottomSheetLayout);

    RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter();
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);

    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setAdapter(recyclerViewAdapter);

    // 顶部拖动View的高度(对应布局中50dp的View)
    final int topViewHeight = 50 * getResources().getDisplayMetrics().densityDpi / 160;
    // BottomSheet的peekHeight与总高度
    final int peekHeight = sheetBehavior.getPeekHeight();
    final int sheetTotalHeight = 450 * getResources().getDisplayMetrics().densityDpi / 160;

    // 监听BottomSheet状态变化
    sheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            LinearLayout.LayoutParams rvParams = (LinearLayout.LayoutParams) recyclerView.getLayoutParams();
            if (newState == BottomSheetBehavior.STATE_COLLAPSED || newState == BottomSheetBehavior.STATE_SETTLING) {
                // 半展开/ Settling状态:RecyclerView高度=peekHeight - 顶部View高度
                rvParams.height = peekHeight - topViewHeight;
            } else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
                // 完全展开状态:RecyclerView高度=BottomSheet总高度 - 顶部View高度
                rvParams.height = sheetTotalHeight - topViewHeight;
            }
            recyclerView.setLayoutParams(rvParams);
        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            // 可选:滑动过程中根据偏移量动态调整高度,优化过渡体验
        }
    });

    recyclerView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                sheetBehavior.setDraggable(false);
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                sheetBehavior.setDraggable(true);
            }
            v.onTouchEvent(event);
            return true;
        }
    });
}

可选优化:用尺寸资源替代硬编码

在res/values/dimens.xml中定义尺寸,让代码更易维护:

<dimen name="bottom_sheet_top_view_height">50dp</dimen>
<dimen name="bottom_sheet_total_height">450dp</dimen>

之后在Activity中通过getResources().getDimensionPixelSize(R.dimen.xxx)获取数值即可。

验证效果

修改完成后,当BottomSheet处于半展开(STATE_SETTLING/STATE_COLLAPSED)状态时,RecyclerView的高度会自动适配当前可视区域,列表项可以完全滚动到底部;完全展开时恢复最大高度,保持原有滚动体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 18:48:18