首页 > 其他分享 >Flutter功能性组件(2):弹出框

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

时间:2024-10-11 16:10:48浏览次数:5  
标签:const key Text BuildContext 弹出 context 组件 Flutter

一、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);

  @override
  Widget build(BuildContext context) {
    return Column(
      // 垂直布局
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 平均分布各个 Widget
      crossAxisAlignment: 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);

  @override
  Widget build(BuildContext context) {
    return Column(
      // 垂直布局
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 平均分布各个 Widget
      crossAxisAlignment: 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);
  @override
  Widget 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);
  @override
  Widget 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);

  @override
  Widget 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);
  @override
  Widget 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);

  @override
  Widget build(BuildContext context) {
    return Column(
      // 垂直布局
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 平均分布各个 Widget
      crossAxisAlignment: 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博客


标签:const,key,Text,BuildContext,弹出,context,组件,Flutter
From: https://www.cnblogs.com/linuxAndMcu/p/18458662

相关文章

  • Flutter基础组件(7):进度条
    在Flutter应用开发中,无论是处理网络请求,执行耗时任务,或是等待用户响应,我们总是需要在界面上显示进度条或者等待指示器。在这篇博客中,我们将介绍Flutter中两种常用的进度指示器:LinearProgressIndicator和CircularProgressIndicator。我们将比较它们的异同点,以及如何使用和自......
  • Flutter基础组件(6):单选按钮、复选框、单选开关
    在移动应用开发中,单选和复选是常见的用户交互模式,用于选择一个或多个选项。Flutter提供了一些内置的组件和机制,方便我们实现单选和复选功能。本文将介绍Flutter中的单选按钮(RadioButton)和复选框(Checkbox)的使用方法和示例。一、单选按钮(RadioButton)单选按钮是一种用户界面组件......
  • Flutter布局(2):弹性布局(Flex、Expanded)
    一、什么是弹性布局(Flex)什么是弹性布局(Flex)?弹性布局(Flex)是一种基于弹性盒子模型的布局方式,类似于Web开发中的Flexbox。在Flutter中,Flex组件是用于实现弹性布局的关键组件之一。Flex布局是一种简洁且强大的方式,可用于构建水平或垂直方向的弹性布局。Flex组件可以沿着水平......
  • Flutter布局(1):线性布局(Row、Column)
    所谓线性布局,即指沿水平或垂直方向排列子组件。Flutter中通过Row和Column来实现线性布局。主轴和纵轴对于线性布局,有主轴和纵轴之分,如果布局是沿水平方向,那么主轴就是指水平方向,而纵轴即垂直方向;如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向。一、Row组件1.1......
  • Flutter布局(4):层叠布局(Stack、Positioned)
    层叠布局和Web中的绝对定位、Android中的Frame布局是相似的,子组件可以根据距父容器四个角的位置来确定自身的位置。层叠布局允许子组件按照代码中声明的顺序堆叠起来。Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位。Stack允许子组件堆叠,而Positioned用于根据......
  • Flutter布局(3):流式布局(Wrap、Flow)
    一、简介在Flutter中,流式布局是一种常用的布局方式,用于实现动态调整子组件位置和尺寸的需求。Flutter提供了两个流式布局的组件:Wrap和Flow。其实,Flow用的实在不多呀。二、Wrap组件Wrap组件是一种流式布局,它会自动调整和换行子组件,以适应可用空间。属性Wrap组件具有......
  • Flutter布局(5):对齐与居中布局(Align、Center)
    在Flutter中,布局是构建用户界面的重要组成部分。Align和Center是两个常用的布局组件,它们都用于在父组件中对子组件进行对齐和居中。本篇博客将详细介绍Align和Center的用法、属性和适用场景,帮助你更好地理解和运用它们。一、Align:精准对齐,掌握位置Align组件用于将子组......
  • vue3父组件调用子组件方法的大坑
    父组件:<template><ChildComponentref="callChildMethod"/></template><scriptsetup>import{ref}from'vue';importChildComponentfrom'./ChildComponent.vue';constcallChildMethod=ref();......
  • springboot多项目融合为springcloud微服务项目(2)之各组件之间的作用
    一、各组件之间的作用1、Nacos主要用于服务主持与发现、配置中心、负载均衡等使用的方法为:nacos依赖①、引用其nacos-discovery和nacos-configdiscovery:主要用于将服务注册到nacos中config:主要用于发现nacos中的配置文件列表,找到对应的配置文件②、将连接nacos的配置信息......
  • web端ant-design-vue Modal.info组件自定义icon和title使用小节
     web端ant-design-vueModal.info组件自定义icon和title整理小节,最近在项目中用到了自定义icon和title的功能,经过测试发现,如果自定义icontitle会自动换行,尝试直接修改样式和穿透方式都没有效果,最后采取了一个巧妙的方式,将icon和title放在一个自定义组件内,完美解决!代码如下......