Flutter功能性组件(2):弹出框

news/2024/10/11 16:18:41

一、showModalBottomSheet(模态底部弹出框)

showModalBottomSheet 用于显示一个模态底部弹出框。

属性解析:

Future<T?> showModalBottomSheet<T>({required BuildContext context, // 表示底部弹出框所处的上下文,通常来自当前 widget。required WidgetBuilder builder, // 用于构建弹出框内容的函数。它传递一个 BuildContext 并返回一个 Widget,这通常是弹出框的主体。Color? backgroundColor, // 底部弹出框的背景颜色。String? barrierLabel, // 屏障的语义标签,用于无障碍功能。double? elevation, // 底部弹出框的阴影高度。ShapeBorder? shape, // 底部弹出框的形状,例如圆角矩形。Clip? clipBehavior, // 如何裁剪底部弹出框的内容。BoxConstraints? constraints, // 底部弹出框的布局约束。Color? barrierColor, // 弹出框背景障碍物(屏幕其余部分)的颜色。bool isScrollControlled = false, // 是否允许弹出框内部滚动。默认为 false。double scrollControlDisabledMaxHeightRatio = _defaultScrollControlDisabledMaxHeightRatio, // 在禁用滚动控制时,最大高度的比例。bool useRootNavigator = false, // 是否使用根导航器来推送弹出框。默认为 false。bool isDismissible = true, // 指示用户点击屏幕背景(弹出框外部)时是否关闭弹出框。默认为 true。bool enableDrag = true, // 是否允许通过拖动来关闭弹出框。默认为 true。bool? showDragHandle, // 是否显示拖动手柄。bool useSafeArea = false, // 是否考虑安全区域(如异形屏幕的凹槽、状态栏等)。默认为 false。RouteSettings? routeSettings, // 传递给弹出框路由的配置信息,如名称和参数。AnimationController? transitionAnimationController, // 自定义弹出框的动画控制器。Offset? anchorPoint, // 指定弹出框弹出的锚点位置。
})

示例:

// 主页面
class MyHomeBody extends StatelessWidget {const MyHomeBody({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Column(// 垂直布局mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 平均分布各个 WidgetcrossAxisAlignment: CrossAxisAlignment.stretch, // 填充整个交叉轴mainAxisSize: MainAxisSize.max,children: <Widget>[ElevatedButton(onPressed: () {_showMyModalBottomSheet(context);},style: ElevatedButton.styleFrom(minimumSize: const Size(160, 80),),child: Text("AlertDialog(提示对话框)"),),],);}
}// showModalBottomSheet(模态底部弹出框)
Future<void> _showMyModalBottomSheet(BuildContext context) async {return showModalBottomSheet<void>(context: context,backgroundColor: Colors.white,shape: RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(25.0)),),isScrollControlled: true,builder: (BuildContext context) {return Padding(padding: const EdgeInsets.all(16.0),child: SingleChildScrollView(child: Column(mainAxisSize: MainAxisSize.min,children: <Widget>[Text('This is a modal bottom sheet.'),SizedBox(height: 20),ElevatedButton(child: Text('Close'),onPressed: () {Navigator.of(context).pop();},),],),),);},);
}

效果图如下所示:

Flutter_dialog_G.png


二、Persistent Bottom Sheet(Scaffold的showBottomSheet方法)

这个方法显示一个持久的底部弹出层,不会在点击外部区域时自动关闭。

属性解析:

PersistentBottomSheetController showBottomSheet(WidgetBuilder builder, { // 用于构建弹出框内容的函数。它传递一个 BuildContext 并返回一个 Widget,这通常是弹出框的主体。Color? backgroundColor, // 底部弹出框的背景颜色double? elevation, // 底部弹出框的阴影高度。ShapeBorder? shape, // 底部弹出框的形状,例如圆角矩形。Clip? clipBehavior, // 如何裁剪底部弹出框的内容。BoxConstraints? constraints, // 底部弹出框的布局约束。bool? enableDrag, // 是否允许通过拖动来关闭弹出框。AnimationController? transitionAnimationController, // 自定义弹出框的动画控制器。})

示例:

// 主页面
class MyHomeBody extends StatelessWidget {const MyHomeBody({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Column(// 垂直布局mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 平均分布各个 WidgetcrossAxisAlignment: CrossAxisAlignment.stretch, // 填充整个交叉轴mainAxisSize: MainAxisSize.max,children: <Widget>[ElevatedButton(onPressed: () {Scaffold.of(context).showBottomSheet((BuildContext context) {return Container(color: Colors.white,height: 200,child: Center(child: Column(mainAxisSize: MainAxisSize.min,children: <Widget>[ListTile(leading: Icon(Icons.photo),title: Text('照片'),onTap: () {},),ListTile(leading: Icon(Icons.music_note),title: Text('音乐'),onTap: () {},),ListTile(leading: Icon(Icons.videocam),title: Text('视频'),onTap: () {},),],),),);},);},child: Text('显示持久底部弹出层'),),],);}
}

效果图如下所示:

Flutter_dialog_H.png


三、PopupMenuButton(弹出菜单)

PopupMenuButton 是一个 Flutter widget,用于显示弹出菜单,当用户点击按钮时,会显示一组选项。

属性解析:

const PopupMenuButton({super.key, // 控件的键值,用于标识控件。required this.itemBuilder, // 构建菜单项的函数,返回一个 List<PopupMenuEntry>。this.initialValue, // 菜单打开时选中的初始值。this.onOpened, // 菜单打开时的回调函数。this.onSelected, // 菜单选项被选中后的回调函数。this.onCanceled, // 菜单被取消时的回调函数。this.tooltip, // 按钮的提示文本。this.elevation, // 菜单的阴影高度。this.shadowColor, // 菜单阴影的颜色。this.surfaceTintColor, // 表面色调的颜色(用于材料设计3)。this.padding = const EdgeInsets.all(8.0), // 按钮的内边距。默认值为 EdgeInsets.all(8.0)。this.child, // 按钮的子小部件。如果不提供,将使用 icon。this.splashRadius, // 按钮点击时水波纹的半径。this.icon, // 按钮的图标。如果不提供,将使用 child。this.iconSize, // 图标的大小。this.offset = Offset.zero, // 菜单相对于按钮的偏移量。默认值为 Offset.zero。this.enabled = true, // 按钮是否可用。默认为 true。this.shape, // 菜单的外形。this.color, // 菜单的背景颜色。this.iconColor, // 图标的颜色。this.enableFeedback, // 是否启用声音和触觉反馈。this.constraints, // 按钮的约束条件。this.position, // 菜单的位置。this.clipBehavior = Clip.none, // 菜单的剪裁行为。this.useRootNavigator = false, // 是否使用根导航器来推送菜单。默认为 false。this.popUpAnimationStyle, // 弹出菜单的动画样式。
})

示例:

// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text("Dialog Page"),),body: PopupMenuButtonDemo(),),);}
}class PopupMenuButtonDemo extends StatelessWidget {const PopupMenuButtonDemo({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Center(child: PopupMenuButton<String>(onSelected: (String result) {print('Selected: $result');},itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[const PopupMenuItem<String>(value: 'Option 1',child: Text('Option 1'),),const PopupMenuItem<String>(value: 'Option 2',child: Text('Option 2'),),const PopupMenuItem<String>(value: 'Option 3',child: Text('Option 3'),),],icon: Icon(Icons.more_vert),offset: Offset(0, 50), // 设置菜单相对于按钮的偏移量elevation: 8.0,onCanceled: () {print('Menu canceled');},tooltip: 'Show options',),);}
}

效果图如下所示:

Flutter_dialog_I.png


四、ExpansionPanelList(展开和折叠的面板)

ExpansionPanelList 是一个 Flutter widget,用于显示一组可以展开和折叠的面板。每个面板在展开状态下可以显示更多内容,非常适合展示分层或分段的信息。

属性解析:

const ExpansionPanelList({super.key, // 控件的键值,用于标识控件。this.children = const <ExpansionPanel>[], // 要显示的扩展面板列表。每个 ExpansionPanel 可以包含标题和内容。this.expansionCallback, // 当某个面板展开或折叠时触发的回调函数。接受两个参数:面板索引和当前的展开状态。this.animationDuration = kThemeAnimationDuration, // 展开和折叠动画的持续时间。this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding, // 已展开面板标题的内边距。this.dividerColor, // 面板之间分隔线的颜色。this.elevation = 2, // 面板的阴影高度。this.expandIconColor, // 扩展图标的颜色。this.materialGapSize = 16.0, // 面板之间的间隙大小。
})

示例:

expansionPanelList.dart

// expansionPanelList.dart
// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';class ExpansionPanelListDemo extends StatefulWidget {const ExpansionPanelListDemo({Key? key}) : super(key: key);@override_ExpansionPanelListDemoState createState() => _ExpansionPanelListDemoState();
}class _ExpansionPanelListDemoState extends State<ExpansionPanelListDemo> {final List<Item> _data = generateItems(3);@overrideWidget build(BuildContext context) {return SingleChildScrollView(child: Container(padding: EdgeInsets.all(10.0),child: ExpansionPanelList(animationDuration: Duration(milliseconds: 500),expansionCallback: (int index, bool isExpanded) {setState(() {_data[index].isExpanded = !isExpanded;});},children: _data.map<ExpansionPanel>((Item item) {return ExpansionPanel(headerBuilder: (BuildContext context, bool isExpanded) {return ListTile(title: Text(item.headerValue),);},body: ListTile(title: Text(item.expandedValue),subtitle: Text('To delete this panel, tap the trash icon'),trailing: Icon(Icons.delete),onTap: () {setState(() {_data.removeWhere((currentItem) => item == currentItem);});},),isExpanded: item.isExpanded,);}).toList(),),),);}
}class Item {Item({required this.expandedValue,required this.headerValue,this.isExpanded = false,});String expandedValue;String headerValue;bool isExpanded;
}List<Item> generateItems(int numberOfItems) {return List<Item>.generate(numberOfItems, (int index) {return Item(headerValue: 'Panel $index',expandedValue: 'This is item number $index',);});
}

main.dart

// ignore_for_file: prefer_const_constructors
import 'package:flutter/material.dart';
import 'widgets/expansionPanelList.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: Text("Dialog Page"),),body: ExpansionPanelListDemo(),),);}
}

效果图如下所示:

Flutter_dialog_J.png


五、SnackBar

SnackBar 是一个 Flutter 小部件,用于显示短暂的消息,通常在屏幕底部。

属性解析:

const SnackBar({super.key, // 用于标识小部件的唯一键。required this.content, // SnackBar 的主要内容,通常是一个 Text 小部件。this.backgroundColor, // 背景颜色。this.elevation, // 阴影高度。this.margin, // 外边距。this.padding, // 内边距。this.width, // 宽度。this.shape, // 形状,例如圆角矩形。this.hitTestBehavior, // 命中测试行为,决定如何处理点击事件。this.behavior, // SnackBar 的行为,可能是固定的或浮动的。this.action, // SnackBar 上的操作按钮。this.actionOverflowThreshold, // 操作按钮溢出的阈值。this.showCloseIcon, // 是否显示关闭图标。this.closeIconColor, // 关闭图标的颜色。this.duration = _snackBarDisplayDuration, // 显示时长。默认为 _snackBarDisplayDuration。this.animation, // 自定义动画。this.onVisible, // SnackBar 可见时调用的回调函数。this.dismissDirection, // SnackBar 可以被滑动以消失的方向。this.clipBehavior = Clip.hardEdge, // 裁剪行为,默认值为 Clip.hardEdge。
})

示例:

class SnackBarDemo extends StatelessWidget {const SnackBarDemo({Key? key}) : super(key: key);void _showSnackBar(BuildContext context) {final snackBar = SnackBar(content: Text('This is a Snackbar!'),action: SnackBarAction(label: 'Undo',onPressed: () {// Some code to undo the change.},),backgroundColor: Colors.blue,elevation: 10.0,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0),),duration: Duration(seconds: 3),);ScaffoldMessenger.of(context).showSnackBar(snackBar);}

效果图如下所示:

Flutter_dialog_K.png


六、自定义BottomSheet

如果你需要一个完全自定义的 BottomSheet 而不是使用 showModalBottomSheet 或 Scaffold.showBottomSheet,你可以直接创建一个自定义的 BottomSheet 组件:

// 主页面
class MyHomeBody extends StatelessWidget {const MyHomeBody({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Column(// 垂直布局mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 平均分布各个 WidgetcrossAxisAlignment: CrossAxisAlignment.stretch, // 填充整个交叉轴mainAxisSize: MainAxisSize.max,children: <Widget>[ElevatedButton(onPressed: () {showCustomBottomSheet(context);},style: ElevatedButton.styleFrom(minimumSize: const Size(160, 80),),child: Text("AlertDialog(提示对话框)"),),],);}
}void showCustomBottomSheet(BuildContext context) {showModalBottomSheet(context: context,builder: (BuildContext context) {return Container(height: 300,padding: EdgeInsets.all(16),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.only(topLeft: Radius.circular(20),topRight: Radius.circular(20),),),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Text('自定义底部弹出层',style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),),SizedBox(height: 16),Text('你可以在这里放置任何内容。'),SizedBox(height: 16),ElevatedButton(onPressed: () {Navigator.pop(context);},child: Text('关闭'),),],),);},);
}

效果图如下所示:

Flutter_dialog_L.png


参考:

Flutter 初识:对话框和弹出层_flutter 正在发布 弹出层-CSDN博客


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/70261.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Flutter容器(6):页面骨架(Scaffold)

Material 组件库提供了丰富多样的组件,这里介绍一下最常用的 Scaffold 组件,其余的读者可以自行查看文档或 Flutter Gallery 中 Material 组件部分的示例。注意:Flutter Gallery 是 Flutter 官方提供的 Flutter Demo,源码位于 flutter 源码中的 examples 目录下,笔者强烈建…

Golang上下文context

上篇内容我们主要讲解了net/http标准库的使用,其中包含如何创建POST请求、GET请求以及如何携带参数的请求。 Context介绍 context释义为上下文,在我们使用goroutine时一般使用context来进行元数据的传递,非元数据不建议使用context来进行传递。那么我们主要是用context用来做…

2024 最新 IntelliJ IDEA 2024.1.6 激活(亲测可用)

注意:接下来本文分享免费激活 IDEA 等Jetbrains全家桶工具,一直支持到最新版本2024.1.6。 1.下载安装IDEA (mac、window、linux都支持) 大家直接在官网下载最新版本,登陆官网,下载最新版本2024.1.4。一步一步确定安装,然后打开 这里提示输入激活码,先关闭应用!!!2.…

淘宝程序员没活硬整?在 Excel 和 VSCode 中购物!

你可以在 Excel 表格中挑选商品进行购物,还原度极高,这两个图表更是点睛之笔。哪个天才想出来的,把特么广告都整成了 Excel 图表。大家好,我是程序员鱼皮,最近某宝网站的改进,属实是有点 “新” 了。 你敢相信这是一个购物网站么?你可以在 Excel 表格中挑选商品进行购物…

Golang模板template

背景概述 当我们在进行json字段选取以及渲染时,我们经常会见到{{}},其实这就是我们今天要讲解的模板即是template。例如prometheusAlert中的模板就是使用了改语法。 必备技能字段选取 ❝ {{ . }} 表示json的所有域,例如:{"name":"anruo","age&quo…

如何在springboot中,全局配置produces=text/plain;charset=UTF-8

为什么要使用produces="text/plain;charset=UTF-8"? 当不用这个配置时,接口返回的数据,是有斜杠的 配置后,就正常了 以前我的配置方式,是在每个接口上,都添加上produces="text/plain;charset=UTF-8"。但是这样显示不太好,每个接口都加的话,会比较…

鸿蒙发送消息通知

注意:发送消息通知要开启设置中的消息通知import notify from @ohos.notificationManager import image from @ohos.multimedia.image import { BusinessError } from @kit.BasicServicesKit@Entry @Component struct NotificationPage {// 全局任务ididx: number = 100// 图象…

域名解析错误是不是被限制了?

在我们畅游互联网的过程中,有时会遭遇域名解析错误的情况,这无疑会给我们的上网体验带来困扰。而很多人在遇到域名解析错误时,不禁会疑惑:这是不是意味着被限制了呢? 首先,域名解析错误并不一定意味着被限制。 域名解析是将域名转换为对应的IP地址的过程,就如同在电话簿…