底部弹窗方法:showModalBottomSheet

  1. 是什么
  2. 常用属性
  3. 案例

是什么

showModalBottomSheet是 Flutter 内置的一个非常常用的底部弹窗方法,用来显示模态(遮罩)底部浮层。

  • 功能:从屏幕底部弹出一个浮层,遮罩背景,阻止用户点击弹窗之外的区域(默认可以点击关闭)
  • 类型:模态弹窗(Modal) → 弹出时背景会变暗,阻止与底部内容交互。
  • 返回值:一个 Future<T?>,当弹窗关闭时返回用户选择的数据(如果你通过 Navigator.pop(context, result) 传入)。

常用属性

属性 含义
context 必填,BuildContext
builder 必填,返回弹窗内容 Widget
isScrollControlled 默认为 false,true 时内容可滚动、可超过屏幕高度
backgroundColor 弹窗背景颜色
elevation 弹窗阴影高度
shape 弹窗形状(一般设置顶部圆角)
clipBehavior 裁剪行为,配合 shape 使用
barrierColor 背景遮罩颜色,默认半透明黑
barrierDismissible 是否允许点击遮罩关闭弹窗(默认 true)
useRootNavigator 是否使用根 Navigator,控制层级

案例

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const BottomSheetDemoPage(),
    );
  }
}

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

  @override
  State<BottomSheetDemoPage> createState() => _BottomSheetDemoPageState();
}

class _BottomSheetDemoPageState extends State<BottomSheetDemoPage> {
  String _result = "未选择";

  void _showBottomSheet() async {
    // Future<T?> showModalBottomSheet<T>({
    // Navigator.pop(context, "选项 ${index + 1}");
    // 这里的 result = "选项 ${index + 1}";
    final result = await showModalBottomSheet<String>(
      // BuildContext get context { ...... }
      context: context,
      isScrollControlled: true, // 内容可滚动
      backgroundColor: Colors.white,
      // RoundedRectangleBorder 表示一个圆角矩形边框
      shape: const RoundedRectangleBorder(
        // borderRadius 属性用于设置圆角的半径
        // BorderRadius.vertical 表示只设置垂直方向的圆角
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      // builder 是一个回调函数,返回一个 Widget,表示底部弹窗的内容
      builder: (context) {
        return SizedBox(
          height: 400, // 可以根据内容高度调整
          child: Column(
            children: [
              // 顶部拖拽手柄:一个居中的灰色的横杠
              // 这个主要是给用户一个提示,表示这个弹窗是可以拖拽的
              // 其实没有这个也可以拖拽
              Container(
                width: 40,
                height: 4,
                margin: const EdgeInsets.symmetric(vertical: 12),
                decoration: BoxDecoration(
                  color: Colors.grey[400],
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
              // 标题
              const Text(
                "请选择一个选项",
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 12),
              // 可滚动内容
              Expanded(
                child: ListView.builder(
                  padding: const EdgeInsets.all(16),
                  itemCount: 20,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text("选项 ${index + 1}"),
                      onTap: () {
                        // 点击选项时,关闭弹窗并返回选中的值
                        // 第二个参数就是返回的结果
                        // Navigator.pop 的第二个作用是关闭弹窗
                        Navigator.pop(context, "选项 ${index + 1}");
                      },
                    );
                  },
                ),
              ),
            ],
          ),
        );
      },
    );

    // 获取返回值
    if (result != null) {
      setState(() {
        _result = result;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("BottomSheet Demo")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("选择结果:$_result", style: const TextStyle(fontSize: 18)),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _showBottomSheet,
              child: const Text("打开底部弹窗"),
            ),
          ],
        ),
      ),
    );
  }
}

×

喜欢就点赞,疼爱就打赏