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

Flutter初学者如何实现主窗口右侧弹窗(类似Bottom Sheet)及打开右侧对话框

Flutter实现右侧滑出弹窗(类似Bottom Sheet)与右侧对话框

嘿,作为Flutter新手,想要实现从右侧滑出的类似Bottom Sheet的弹窗,还有右侧对话框对吧?我给你整理了两种最实用的实现方式,都是新手能快速上手的~


一、实现右侧滑出的侧边栏(类似Bottom Sheet效果)

Bottom Sheet默认是从底部弹出,我们要做右侧滑入的效果,这里有两种方案:

1. 用Scaffold自带的endDrawer(最简单)

Flutter的Scaffold组件自带了右侧抽屉endDrawer,默认就是从右侧滑入,完全满足类似Bottom Sheet的交互需求,代码量极少:

Scaffold(
  appBar: AppBar(title: const Text('右侧侧边栏示例')),
  body: Center(
    child: ElevatedButton(
      onPressed: () {
        // 触发打开右侧抽屉
        Scaffold.of(context).openEndDrawer();
      },
      child: const Text('打开右侧弹窗'),
    ),
  ),
  endDrawer: Drawer(
    // 设置弹窗宽度为屏幕的70%,可以根据需求调整
    width: MediaQuery.of(context).size.width * 0.7,
    child: Container(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text('右侧侧边栏内容', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          const SizedBox(height: 20),
          ListTile(title: const Text('选项1')),
          ListTile(title: const Text('选项2')),
          // 把内容顶到底部
          const Spacer(),
          ElevatedButton(
            onPressed: () {
              // 关闭侧边栏
              Navigator.of(context).pop();
            },
            child: const Text('关闭'),
          )
        ],
      ),
    ),
  ),
)

小提示:关闭侧边栏除了用Navigator.pop(),也可以调用Scaffold.of(context).closeEndDrawer(),效果是一样的。

2. 自定义动画侧边栏(更灵活)

如果想要更个性化的动画(比如淡入+滑入结合)、自定义遮罩层样式,那就用AnimatedContainer结合Stack来实现:

class RightSideSheetDemo extends StatefulWidget {
  const RightSideSheetDemo({super.key});

  @override
  State<RightSideSheetDemo> createState() => _RightSideSheetDemoState();
}

class _RightSideSheetDemoState extends State<RightSideSheetDemo> {
  bool _isSheetOpen = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('自定义右侧弹窗')),
      body: Stack(
        children: [
          // 主页面内容
          Center(
            child: ElevatedButton(
              onPressed: () {
                setState(() {
                  _isSheetOpen = true;
                });
              },
              child: const Text('打开自定义右侧弹窗'),
            ),
          ),
          // 遮罩层:点击关闭弹窗
          if (_isSheetOpen)
            GestureDetector(
              onTap: () {
                setState(() {
                  _isSheetOpen = false;
                });
              },
              child: Container(color: Colors.black.withOpacity(0.5)),
            ),
          // 右侧弹窗本体
          AnimatedContainer(
            duration: const Duration(milliseconds: 300),
            curve: Curves.easeInOut,
            // 控制弹窗宽度:打开时占屏幕70%,关闭时宽度为0
            width: _isSheetOpen ? MediaQuery.of(context).size.width * 0.7 : 0,
            height: double.infinity,
            decoration: const BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(16),
                bottomLeft: Radius.circular(16),
              ),
            ),
            child: _isSheetOpen
                ? Container(
                    padding: const EdgeInsets.all(16),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        const Text('自定义右侧弹窗', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                        const SizedBox(height: 20),
                        const Expanded(child: Text('这里可以放任何你想要的内容:表单、列表、图片都没问题')),
                        ElevatedButton(
                          onPressed: () {
                            setState(() {
                              _isSheetOpen = false;
                            });
                          },
                          child: const Text('关闭'),
                        )
                      ],
                    ),
                  )
                : const SizedBox.shrink(),
          ),
        ],
      ),
    );
  }
}

这种方式完全由你掌控样式和动画,适合需要高度定制的场景。


二、实现右侧对话框(Dialog)

默认的Dialog是居中显示的,要让它贴在右侧,只需要用Align组件调整位置即可:

// 封装成方法,方便调用
void showRightSideDialog(BuildContext context) {
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return Align(
        // 把对话框定位在屏幕右侧居中位置
        alignment: Alignment.centerRight,
        child: Container(
          width: MediaQuery.of(context).size.width * 0.6,
          height: MediaQuery.of(context).size.height * 0.8,
          decoration: const BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(16),
              bottomLeft: Radius.circular(16),
            ),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Padding(
                padding: EdgeInsets.all(16),
                child: Text('右侧对话框', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
              ),
              const Divider(height: 0),
              const Expanded(
                child: Padding(
                  padding: EdgeInsets.all(16),
                  child: Text('对话框的内容区域,可以放表单、提示信息等'),
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(16),
                child: ElevatedButton(
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                  child: const Text('关闭'),
                ),
              )
            ],
          ),
        ),
      );
    },
    // 设置遮罩层透明度
    barrierColor: Colors.black.withOpacity(0.5),
  );
}

// 调用方式:在按钮点击时触发
// ElevatedButton(
//   onPressed: () => showRightSideDialog(context),
//   child: const Text('打开右侧对话框'),
// )

这种方法本质还是用Flutter原生的showDialog,只是调整了对话框的位置,上手毫无难度。


总结一下

  • 如果只是需要简单的右侧滑出弹窗,优先用Scaffold.endDrawer,快速又省心;
  • 追求定制化效果,就用自定义动画的方案;
  • 右侧对话框直接通过Align调整原生Dialog的位置即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 20:58:11