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

能否在DraggableScrollableSheet内设置独立滚动区域?

解决方案

要实现仅顶部区域可拖动展开Bottom Sheet,同时底部列表独立滚动且子组件尺寸固定,需要对代码做以下调整:

  • 给顶部区域添加拖动监听,通过DraggableScrollableActuator控制Sheet的展开状态
  • 底部ListView使用独立的ScrollController,避免与Sheet的滚动控制器关联
  • 配置DraggableScrollableSheet的最小/最大尺寸,明确Sheet的可拖动范围

修改后的完整代码:

@override
Widget build(BuildContext context) {
  // 给底部列表单独创建滚动控制器
  final listScrollController = ScrollController();

  return BlocBuilder<CompetitionCubit, Competition>(
    builder: (context, state) {
      return DraggableScrollableSheet(
        // 设置Sheet的最小/最大展示尺寸
        minChildSize: 0.3,
        maxChildSize: 0.9,
        builder: (context, sheetScrollController) {
          return Container(
            decoration: const BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(20),
                topRight: Radius.circular(20),
              ),
              boxShadow: [
                BoxShadow(
                  color: Colors.grey,
                  blurRadius: 10.0,
                ),
              ],
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                // 顶部拖动区域:用GestureDetector监听垂直拖动
                GestureDetector(
                  onVerticalDragUpdate: (details) {
                    // 通过拖动偏移量计算Sheet的目标尺寸
                    final currentSize = sheetScrollController.position.viewportDimension / MediaQuery.of(context).size.height;
                    final newSize = currentSize - details.delta.dy / MediaQuery.of(context).size.height;
                    // 限制尺寸在min和max之间
                    final clampedSize = newSize.clamp(0.3, 0.9);
                    // 更新Sheet的尺寸
                    DraggableScrollableActuator.reset(context, to: clampedSize);
                  },
                  child: const Padding(
                    padding: EdgeInsets.all(16.0),
                    child: Text(
                      'Draggable top section',
                      style: TextStyle(fontSize: 24),
                    ),
                  ),
                ),
                const Divider(
                  thickness: 1,
                  color: Colors.grey,
                ),
                // 底部列表区域:使用独立的滚动控制器
                Expanded(
                  child: ListView.builder(
                    controller: listScrollController,
                    itemCount: 50,
                    itemBuilder: (context, index) {
                      return ListTile(
                        title: Text('Item $index'),
                      );
                    },
                  ),
                ),
              ],
            ),
          );
        },
      );
    },
  );
}

关键说明

  1. 顶部拖动逻辑:通过GestureDetector的onVerticalDragUpdate监听拖动动作,计算拖动偏移对Sheet尺寸的影响,再用DraggableScrollableActuator.reset()更新Sheet的展示比例,同时限制尺寸在最小/最大值范围内,避免超出边界。
  2. 独立滚动列表:给ListView单独设置ScrollController,这样列表的滚动操作不会触发Sheet的拖动,实现两者的交互分离。
  3. 尺寸控制:通过minChildSize和maxChildSize明确Sheet的可拖动范围,确保用户操作的合理性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:06:04