是什么
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("打开底部弹窗"),
),
],
),
),
);
}
}