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

如何在showModalBottomSheet中使用DraggableScrollableSheet并固定顶部栏

解决思路

要实现拖拽底部弹窗时标题栏固定不跟随滚动,只需要把固定标题栏和可拖拽滚动的内容区做层级拆分即可,核心结构如下:

  • 最外层用Column作为弹窗根布局
  • 第一层直接放你需要的固定标题栏(AppBar或者自定义Container都可以)
  • 第二层用Expanded包裹DraggableScrollableSheet,内部放你的可滚动内容(SingleChildScrollView/ListView)

这样拆分后标题栏会固定在弹窗顶部,只有下方内容区会跟随拖拽动作上下滚动。

修正后完整代码

bottomsheet(context) {
  Size size = MediaQuery.of(context).size;
  return showModalBottomSheet(
      backgroundColor: Colors.white,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(13)),
      ),
      context: context,
      // 重点:开启isScrollControlled让弹窗支持撑满高度
      isScrollControlled: true,
      builder: (BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(5),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // 固定标题栏,不会跟随滚动
              AppBar(
                foregroundColor: Colors.green,
                backgroundColor: Colors.white,
                elevation: 1,
                shadowColor: Colors.grey.shade100,
                automaticallyImplyLeading: false,
                title: const Text('Connect with Reconnect'),
              ),
              // 可拖拽滚动的内容区
              Expanded(
                child: DraggableScrollableSheet(
                  initialChildSize: 0.5, // 初始展示高度占父容器比例,可自行调整
                  minChildSize: 0.3, // 最小高度比例,可自行调整
                  maxChildSize: 0.9, // 最大高度比例,可自行调整
                  builder: (context, scrollController) {
                    return SingleChildScrollView(
                      // 必须绑定DraggableScrollableSheet提供的scrollController,避免滚动冲突
                      controller: scrollController,
                      child: Padding(
                        padding: const EdgeInsets.all(25),
                        child: Container(
                          padding: const EdgeInsets.only(
                            left: 15,
                            right: 15,
                            top: 15,
                          ),
                          decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.circular(13),
                            boxShadow: const [
                              BoxShadow(blurRadius: 2, color: Colors.grey),
                            ],
                          ),
                          child: Column(children: [
                            TextField(
                              cursorColor: Colors.green,
                              decoration: InputDecoration(
                                label: const Text('Name'),
                                labelStyle: TextStyle(color: Colors.grey.shade500),
                                icon: const Icon(
                                  Icons.person,
                                  color: Color(0xff453e3d),
                                  size: 22,
                                ),
                                border: InputBorder.none,
                              ),
                            ),
                            Container(
                              width: 315,
                              height: 1,
                              margin: const EdgeInsets.only(top: 3, bottom: 3),
                              decoration: BoxDecoration(
                                color: Colors.grey[300],
                                borderRadius: BorderRadius.circular(100),
                              ),
                            ),
                            TextField(
                              cursorColor: Colors.green,
                              decoration: InputDecoration(
                                label: const Text('Email'),
                                labelStyle: TextStyle(color: Colors.grey.shade500),
                                icon: const Icon(
                                  Icons.email,
                                  color: Color(0xff453e3d),
                                  size: 22,
                                ),
                                border: InputBorder.none,
                              ),
                            ),
                            Container(
                              width: 315,
                              height: 1,
                              margin: const EdgeInsets.only(top: 3, bottom: 3),
                              decoration: BoxDecoration(
                                color: Colors.grey[300],
                                borderRadius: BorderRadius.circular(100),
                              ),
                            ),
                            TextField(
                              cursorColor: Colors.green,
                              decoration: InputDecoration(
                                label: const Text('Phone Number'),
                                labelStyle: TextStyle(color: Colors.grey.shade500),
                                icon: const Icon(
                                  Icons.phone_android,
                                  color: Color(0xff453e3d),
                                  size: 22,
                                ),
                                border: InputBorder.none,
                              ),
                            ),
                            Container(
                              width: 315,
                              height: 1,
                              margin: const EdgeInsets.only(top: 3, bottom: 3),
                              decoration: BoxDecoration(
                                color: Colors.grey[300],
                                borderRadius: BorderRadius.circular(100),
                              ),
                            ),
                            Container(
                              margin: const EdgeInsets.only(top: 10),
                              height: 25,
                              alignment: Alignment.bottomLeft,
                              child: Row(
                                children: [
                                  const Icon(
                                    Icons.directions_car,
                                    color: Color(0xff453e3d),
                                  ),
                                  const SizedBox(
                                    width: 15,
                                  ),
                                  Text(
                                    'Services',
                                    style: TextStyle(
                                        color: Colors.grey.shade500, fontSize: 16),
                                  ),
                                ],
                              ),
                            ),
                          ]),
                        ),
                      ),
                    );
                  },
                ),
              )
            ],
          ),
        );
      });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:09:03