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

Flutter Web中DraggableScrollableSheet日期选择器跳项问题求助

解决方案:Flutter Web中DraggableScrollableSheet嵌套CupertinoDatePicker滚动跳项问题

问题根源

出现滚动跳项的核心原因是DraggableScrollableSheet的拖拽/滚动手势与CupertinoDatePicker自身的滚轮滚动手势在Web平台上发生冲突,导致事件被干扰,无法正常响应连续的滚动选择。

解决方案

方案一:移除DraggableScrollableSheet(推荐,若无需拖拽调整弹窗大小)

如果你的场景不需要拖拽调整底部弹窗的尺寸,直接去掉DraggableScrollableSheet,用普通的showModalBottomSheet即可解决冲突:

void _showDatePickerBottomSheet(BuildContext context) {
  showModalBottomSheet(
    context: context,
    isScrollControlled: true,
    shape: const RoundedRectangleBorder(
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(25.0),
        topRight: Radius.circular(25.0),
      ),
    ),
    builder: (context) {
      return Container(
        height: 200,
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom,
        ),
        child: CupertinoDatePicker(
          mode: CupertinoDatePickerMode.date,
          initialDateTime: DateTime.now(),
          onDateTimeChanged: (DateTime newDateTime) {
            _readingDate = DateFormat('dd/MM/yyyy').format(newDateTime).toString();
            setState(() {}); // 调用setState更新界面显示
          },
        ),
      );
    },
  );
}

方案二:保留DraggableScrollableSheet,拦截手势冲突

如果必须保留拖拽调整尺寸的功能,需要给CupertinoDatePicker包裹手势拦截器,阻止其区域的滚动事件传递给DraggableScrollableSheet:

void _showDatePickerBottomSheet(BuildContext context) {
  showModalBottomSheet(
    context: context,
    isScrollControlled: true,
    backgroundColor: Colors.transparent,
    builder: (context) {
      return GestureDetector(
        onTap: () {
          Navigator.of(context).pop();
          setState(() {});
        },
        child: Container(
          padding: EdgeInsets.only(
            bottom: MediaQuery.of(context).viewInsets.bottom,
          ),
          color: const Color.fromRGBO(0, 0, 0, 0.001),
          child: GestureDetector(
            onTap: () {},
            child: DraggableScrollableSheet(
              initialChildSize: 0.5,
              minChildSize: 0.2,
              maxChildSize: 1,
              builder: (_, controller) {
                return Container(
                  decoration: const BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.only(
                      topLeft: Radius.circular(25.0),
                      topRight: Radius.circular(25.0),
                    ),
                  ),
                  child: Column(
                    children: [
                      // 顶部拖拽手柄,用于调整弹窗大小(可选,提升交互体验)
                      const SizedBox(
                        height: 40,
                        child: Center(
                          child: Container(
                            width: 40,
                            height: 6,
                            decoration: BoxDecoration(
                              color: Colors.grey,
                              borderRadius: BorderRadius.all(Radius.circular(3)),
                            ),
                          ),
                        ),
                      ),
                      // 拦截日期选择器区域的垂直拖拽事件
                      Expanded(
                        child: GestureDetector(
                          behavior: HitTestBehavior.opaque,
                          onVerticalDragStart: (_) {}, // 拦截垂直拖拽,避免与DraggableSheet冲突
                          child: CupertinoDatePicker(
                            mode: CupertinoDatePickerMode.date,
                            initialDateTime: DateTime.now(),
                            onDateTimeChanged: (DateTime newDateTime) {
                              _readingDate = DateFormat('dd/MM/yyyy').format(newDateTime).toString();
                              setState(() {});
                            },
                          ),
                        ),
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    },
  );
}

额外注意点

  • 记得在onDateTimeChanged回调中调用setState(),确保界面能实时更新选中的日期;
  • Web平台上Cupertino组件的手势兼容性不如移动端,若追求更稳定的体验,也可以考虑使用Flutter官方的showDatePicker替代CupertinoDatePicker。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:35:20