千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > Flutter 弹框全解析

Flutter 弹框全解析

来源:千锋教育
发布人:xqq
时间: 2023-11-23 00:39:12 1700671152

一、基础概念

Flutter中的弹框分为两种类型:Dialog和BottomSheet。Dialog一般指具有模态的弹框,使用showDialog函数实现;而BottomSheet一般指非模态的弹框,使用showModalBottomSheet实现。除此之外,还有一些其他类型的弹框,如底部菜单弹框,选择器弹框等,这里就不一一列举了。

Flutter的弹框构造器通常包括以下几个部分:弹框主体Widget、背景遮罩Widget、动画控制器、弹框位置等等。接下来我们会重点讲述这些部分的实现过程。

二、Dialog的实现

Dialog是模态的弹框类型,即弹框出现时,背景被遮挡且无法操作。

1、弹框主体Widget

在Flutter中,Dialog通常由一个AlertDialog Widget或SimpleDialog Widget构成。其中AlertDialog可以自定义其标题、内容和按钮;而SimpleDialog只包含多个选项。

AlertDialog的构建过程类似下面的代码:


showDialog(
  context: context,
  builder: (BuildContext context) {
    return AlertDialog(
      title: Text("弹框标题"),
      content: Text("弹框内容"),
      actions: [
        FlatButton(
          child: Text("取消"),
          onPressed: () {
            Navigator.of(context).pop();  // 关闭弹框
          },
        ),
        FlatButton(
          child: Text("确定"),
          onPressed: () {
            // 实现确认逻辑
          },
        ),
      ],
    );
  },
);

2、背景遮罩Widget

这里我们使用了showDialog函数来构建Dialog,同时此函数还允许我们自定义弹框显示时的遮罩背景。这可以通过指定barrierColor、barrierOpacity和barrierDismissible等属性来实现。其中,barrierColor和barrierOpacity用于设置遮罩的颜色和透明度,而barrierDismissible则用于控制是否允许用户点击遮罩背景来关闭弹框(即点击空白处关闭弹框)。


showDialog(
  context: context,
  barrierColor: Colors.black12,  // 遮罩颜色
  barrierOpacity: 0.5,  // 遮罩透明度
  barrierDismissible: false,  // 是否允许点击空白处关闭弹框
  builder: (BuildContext context) {
    return AlertDialog(
      //...
    );
  },
);

3、动画控制器

想要Dialog具有更好的动画效果,我们可以使用Flutter内置的动画库Animations。通过AnimatedWidget或AnimatedBuilder等顶层Widget,我们可以方便地构建各种动画效果。这里以FadeTransition为例,演示如何实现Dialog的淡入淡出效果。


class MyDialog extends StatefulWidget {
  const MyDialog({Key key}) : super(key: key);

  @override
  _MyDialogState createState() => _MyDialogState();
}

class _MyDialogState extends State with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    );
    _animation = CurvedAnimation(parent: _controller, curve: Curves.easeOut);

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FadeTransition(
      opacity: _animation,
      child: Center(
        child: AlertDialog(
          title: Text("弹框标题"),
          content: Text("弹框内容"),
          actions: [
            FlatButton(
              child: Text("取消"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: Text("确定"),
              onPressed: () {
                //...
              },
            ),
          ],
        ),
      ),
    );
  }
}

void showMyDialog(BuildContext context) {
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return MyDialog();
    },
  );
}

三、BottomSheet的实现

BottomSheet是非模态的弹框类型,即弹框出现时,背景不被遮挡且可以进行操作。BottomSheet有两种类型:PersistentBottomSheet和ModalBottomSheet。其中,PersistentBottomSheet会一直保持显示直至手动关闭,而ModalBottomSheet会在点击某个按钮后弹出,在外部区域进行操作时自动隐藏。

1、弹框主体Widget

在Flutter中,BottomSheet的构建器是builder属性,它是个函数类型,返回一个Widget。另外我们也可以使用官方提供的BottomSheet Widget。与Dialog不同,BottomSheet不包含标题和按钮等元素,通常只包含一部分滚动内容。


ModalBottomSheet(
  builder: (BuildContext context) {
    return Container(
      height: 200.0,
      child: ListView(
        children: [
          ListTile(title: Text('选项1')),
          ListTile(title: Text('选项2')),
          ListTile(title: Text('选项3')),
          ListTile(title: Text('选项4')),
        ],
      ),
    );
  },
);

2、背景遮罩Widget

与Dialog类似,BottomSheet也有相应的遮罩背景设置属性。但由于其本身不是模态的,所以不需要只读化背景,也就意味着无需设置barrierDismissible属性。


showModalBottomSheet(
  context: context,
  backgroundColor: Colors.black12,  // 设置背景色
  builder: (BuildContext context) {
    return Container(
      height: 200.0,
      child: ListView(
        children: [
          //...
        ],
      ),
    );
  },
);

3、动画控制器

维护动画控制器实现BottomSheet的进入和退出动画。


class MyBottomSheet extends StatefulWidget {
  const MyBottomSheet({Key key}) : super(key: key);

  @override
  _MyBottomSheetState createState() => _MyBottomSheetState();
}

class _MyBottomSheetState extends State with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(milliseconds: 500),
      vsync: this,
    );
    _animation = CurvedAnimation(parent: _controller, curve: Curves.easeOut);

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: Tween(
        begin: Offset(0.0, 1.0),
        end: Offset(0.0, 0.0),
      ).animate(_controller),
      child: Container(
        height: 200.0,
        child: ListView(
          children: [
            //...
          ],
        ),
      ),
    );
  }
}

void showMyBottomSheet(BuildContext context) {
  showModalBottomSheet(
    context: context,
    builder: (BuildContext context) {
      return MyBottomSheet();
    },
  );
}

四、结语

以上就是Flutter弹框的实现方案。除了这两种类型外,还有很多其他类型的弹框类型,每种类型都有自己的实现方式。我们需要具体问题具体分析,灵活运用。在实践中不断探索,准确地找到需要用到的弹框类型,并实现对应的构造器。

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT