Flutter对话框对齐插件align_dialog的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter对话框对齐插件align_dialog的使用

align_dialog 是一个 Flutter 包,它允许你打开一个与关联小部件对齐的对话框。在大屏幕设备上,通常的对话框居中显示的行为可能不是最佳选择。这个包让你可以将对话框与触发它的原始小部件对齐。

获取开始

在 Flutter 中,你可以使用 showDialog 函数来打开一个对话框。默认情况下,这个对话框会是一个居中显示的 Dialog 小部件。然而,在大屏幕设备上,这种行为可能并不理想。align_dialog 包允许你将对话框相对于触发它的原始小部件进行对齐。

以下是 showAlignedDialog 函数的接口:

Future<T?> showAlignedDialog<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  bool barrierDismissible = true,
  Color? barrierColor = Colors.black54,
  String? barrierLabel,
  bool useRootNavigator = true,
  RouteSettings? routeSettings,
  Alignment followerAnchor = Alignment.center,
  Alignment targetAnchor = Alignment.center,
  Offset offset = Offset.zero,
  bool avoidOverflow = false,
  bool isGlobal = false,
  RouteTransitionsBuilder? transitionsBuilder,
  Duration? duration,
})

最后七个参数与内置的 showDialog 函数不同。followerAnchortargetAnchor 参数用于指定对话框和原始小部件应该如何对齐,类似于 CompositedTransformFollower 小部件。offset 参数用于额外的微调对话框的位置。

如果 avoidOverflow 设置为 true,对话框会尽可能地移动以避免超出屏幕范围。

如果 isGlobal 设置为 true,对话框将相对于整个屏幕进行对齐,这使得 targetAnchor 参数变得无关紧要。

transitionsBuilder 参数用于指定对话框如何显示和消失。默认行为是一个淡入淡出的过渡效果,但你可以轻松添加更多的动画效果,例如滑动效果。duration 参数指定了过渡效果所需的时间。

你可以在示例文件夹中找到更多例子。

example1

example2

完整示例

以下是一个完整的示例,展示了如何使用 align_dialog 插件来创建不同的对话框。

import 'dart:math';

import 'package:align_dialog/align_dialog.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
          width: MediaQuery.of(context).size.width * 0.8,
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showAlignedDialog(
                            context: context,
                            builder: _localDialogBuilder,
                            followerAnchor: Alignment.topLeft,
                            targetAnchor: Alignment.bottomLeft,
                            barrierColor: Colors.transparent);
                      },
                      child: Text("Tap to show a local dialog"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return MouseRegion(
                    onEnter: (PointerEnterEvent event) {
                      showAlignedDialog(
                          context: context,
                          builder: _localDialogBuilder,
                          followerAnchor: Alignment.topLeft,
                          targetAnchor: Alignment.bottomLeft,
                          barrierColor: Colors.transparent);
                    },
                    child: Container(
                        width: 200,
                        height: 60,
                        color: Colors.orange,
                        child: Text("Hover to show a local dialog")),
                  );
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return GestureDetector(
                    onTap: () {
                      showAlignedDialog(
                          context: context,
                          builder: (BuildContext context) {
                            return Container(
                              decoration: BoxDecoration(
                                  border: Border.all(
                                      color: Colors.black87, width: 5)),
                              child: Column(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Container(
                                    width: 600,
                                    height: 360,
                                    decoration: BoxDecoration(
                                        image: DecorationImage(
                                            fit: BoxFit.cover,
                                            image: NetworkImage(
                                                "https://images.unsplash.com/photo-1612392062422-ef19b42f74df?ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;ixlib=rb-1.2.1&amp;auto=format&amp;fit=crop&amp;w=2550&amp;q=80"))),
                                  ),
                                  Container(
                                    width: 600,
                                    padding: EdgeInsets.symmetric(vertical: 10),
                                    child: Text("Enlarged Image"),
                                    color: Colors.amberAccent,
                                    alignment: Alignment.center,
                                  )
                                ],
                              ),
                            );
                          },
                          followerAnchor: Alignment.topLeft,
                          targetAnchor: Alignment.bottomLeft,
                          barrierColor: Colors.transparent);
                    },
                    child: Container(
                      decoration: BoxDecoration(
                          image: DecorationImage(
                              fit: BoxFit.cover,
                              image: NetworkImage(
                                  "https://images.unsplash.com/photo-1612392062422-ef19b42f74df?ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;ixlib=rb-1.2.1&amp;auto=format&amp;fit=crop&amp;w=2550&amp;q=80"))),
                      alignment: Alignment.centerLeft,
                      width: 150,
                      height: 200,
                    ),
                  );
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showAlignedDialog(
                            context: context,
                            builder: (context) {
                              return AlertDialog(
                                insetPadding: EdgeInsets.zero,
                                title: Text("Alert!"),
                                content: Text("Its an alert"),
                              );
                            },
                            isGlobal: true,
                            followerAnchor: Alignment.center,
                            targetAnchor: Alignment.bottomLeft,
                            barrierColor: Colors.transparent);
                      },
                      child: Text("Tap to show a local alert dialog"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showGlobalDrawer(
                            context: context,
                            builder: _horizontalDrawerBuilder,
                            direction: AxisDirection.left);
                      },
                      child: Text("Tap to show a left drawer"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showGlobalDrawer(
                            context: context,
                            builder: _horizontalDrawerBuilder,
                            direction: AxisDirection.right);
                      },
                      child: Text("Tap to show a right drawer"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showGlobalDrawer(
                            context: context,
                            builder: _verticalDrawerBuilder,
                            direction: AxisDirection.up);
                      },
                      child: Text("Tap to show a top drawer"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showGlobalDrawer(
                            context: context,
                            builder: _verticalDrawerBuilder,
                            direction: AxisDirection.down);
                      },
                      child: Text("Tap to show a bottom drawer"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showAlignedDialog(
                            context: context,
                            builder: _localDialogBuilder,
                            followerAnchor: Alignment.topLeft,
                            targetAnchor: Alignment.bottomLeft,
                            barrierColor: Colors.transparent,
                            //offset: Offset(10, 10),
                            avoidOverflow: true);
                      },
                      child: Text("Tap to show a local dialog"));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showAlignedDialog(
                            context: context,
                            builder: _localDialogBuilder,
                            followerAnchor: Alignment.topLeft,
                            targetAnchor: Alignment.bottomRight,
                            barrierColor: Colors.transparent,
                            avoidOverflow: true);
                      },
                      child: Container(
                          alignment: Alignment.center,
                          width: 300,
                          height: 50,
                          child: Text("Tap to show a local dialog at bottom right")));
                }),
                SizedBox(
                  height: 20,
                ),
                Builder(builder: (context) {
                  return ElevatedButton(
                      onPressed: () {
                        showAlignedDialog(
                            context: context,
                            builder: _localDialogBuilder,
                            followerAnchor: Alignment.bottomRight,
                            targetAnchor: Alignment.topLeft,
                            barrierColor: Colors.transparent,
                            avoidOverflow: true);
                      },
                      child: Container(
                          alignment: Alignment.center,
                          width: 300,
                          height: 80,
                          child: Text("Tap to show a local dialog at top left")));
                }),
                SizedBox(
                  height: 20,
                ),
                Container(
                  height: 100,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: List.generate(
                      10,
                      (index) => Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Builder(builder: (context) {
                            return ElevatedButton(
                                onPressed: () {
                                  showAlignedDialog(
                                      context: context,
                                      builder: _localDialogBuilder,
                                      followerAnchor: Alignment.topLeft,
                                      targetAnchor: Alignment.bottomLeft,
                                      barrierColor: Colors.transparent,
                                      //offset: Offset(10, 10),
                                      avoidOverflow: true);
                                },
                                child: Text("Tap to show a local dialog"));
                          })),
                    ),
                  ),
                ),
                ...List.generate(
                  5,
                  (index) => Container(
                      alignment: Alignment.center,
                      padding: const EdgeInsets.all(8.0),
                      child: Builder(builder: (context) {
                        var rng = new Random();
                        return ElevatedButton(
                            onPressed: () {
                              showAlignedDialog(
                                  context: context,
                                  builder: _localDialogBuilder,
                                  followerAnchor: Alignment.topLeft,
                                  targetAnchor: Alignment.bottomRight,
                                  barrierColor: Colors.transparent,
                                  avoidOverflow: true);
                            },
                            child: Container(
                                alignment: Alignment.center,
                                width: rng.nextInt(300) + 300,
                                height: rng.nextInt(50) + 50,
                                child: Text(
                                    "Tap to show a local dialog at bottom right")));
                      })),
                ),
                ...List.generate(
                  15,
                  (index) => Container(
                      alignment: Alignment.center,
                      margin: EdgeInsets.all(8),
                      child: Builder(builder: (context) {
                        var rng = new Random();
                        return ElevatedButton(
                            onPressed: () {
                              showAlignedDialog(
                                  context: context,
                                  builder: _localDialogBuilder,
                                  followerAnchor: Alignment.bottomRight,
                                  targetAnchor: Alignment.topLeft,
                                  barrierColor: Colors.transparent,
                                  avoidOverflow: true);
                            },
                            child: Container(
                                margin: EdgeInsets.all(rng.nextInt(100).toDouble()),
                                alignment: Alignment.center,
                                width: rng.nextInt(300) + 300,
                                height: rng.nextInt(80) + 20,
                                child: Text(
                                    "Tap to show a local dialog at top left")));
                      })),
                ),
              ]
                ..add(Container(
                  height: 100,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: List.generate(
                      10,
                      (index) => Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Builder(builder: (context) {
                            return ElevatedButton(
                                onPressed: () {
                                  showAlignedDialog(
                                      context: context,
                                      builder: _localDialogBuilder,
                                      followerAnchor: Alignment.topLeft,
                                      targetAnchor: Alignment.bottomLeft,
                                      barrierColor: Colors.transparent,
                                      //offset: Offset(10, 10),
                                      avoidOverflow: true);
                                },
                                child: Text("Tap to show a local dialog"));
                          })),
                    ),
                  ),
                )),
            ),
          ),
        ),
      ),
    );
  }

  WidgetBuilder get _localDialogBuilder {
    return (BuildContext context) {
      return GestureDetector(
        onTap: () {
          Navigator.of(context).pop();
        },
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: 10),
          decoration: BoxDecoration(
              color: Colors.amberAccent,
              borderRadius: BorderRadius.all(Radius.circular(10))),
          child: DefaultTextStyle(
            style: TextStyle(fontSize: 18, color: Colors.black87),
            child: IntrinsicWidth(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  SizedBox(
                    height: 10,
                  ),
                  GestureDetector(
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                      child: Text("Tap to close")),
                  SizedBox(
                    height: 10,
                  ),
                  Divider(
                    height: 4,
                  ),
                  SizedBox(
                    height: 10,
                  ),
                  GestureDetector(
                      onTap: () {
                        print("hello2");
                        //Navigator.of(context).pop();
                      },
                      child: Text("Tap to print")),
                  SizedBox(
                    height: 10,
                  ),
                ],
              ),
            ),
          ),
        ),
      );
    };
  }

  WidgetBuilder get _horizontalDrawerBuilder {
    return (BuildContext context) {
      return GestureDetector(
        onTap: () {
          Navigator.of(context).pop();
        },
        child: Drawer(
          child: Container(
            width: 400,
            padding: EdgeInsets.symmetric(horizontal: 10),
            decoration: BoxDecoration(
              color: Colors.amberAccent,
            ),
            child: DefaultTextStyle(
              style: TextStyle(fontSize: 18, color: Colors.black87),
              child: IntrinsicWidth(
                child: Column(
                  mainAxisSize: MainAxisSize.max,
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    SizedBox(
                      height: 10,
                    ),
                    GestureDetector(
                        onTap: () {
                          Navigator.of(context).pop();
                        },
                        child: Text("Tap to close")),
                    SizedBox(
                      height: 10,
                    ),
                    Divider(
                      height: 4,
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    GestureDetector(
                        onTap: () {
                          print("hello2");
                          //Navigator.of(context).pop();
                        },
                        child: Text("Tap to print")),
                    SizedBox(
                      height: 10,
                    ),
                    Text("Some Text"),
                    SizedBox(
                      height: 10,
                    ),
                    Text("Some Text"),
                    SizedBox(
                      height: 10,
                    ),
                    Text("Some Text"),
                  ],
                ),
              ),
            ),
          ),
        ),
      );
    };
  }

  WidgetBuilder get _verticalDrawerBuilder {
    return (BuildContext context) {
      return GestureDetector(
        onTap: () {
          Navigator.of(context).pop();
        },
        child: Container(
          height: 300,
          padding: EdgeInsets.symmetric(horizontal: 10),
          decoration: BoxDecoration(
            color: Colors.amberAccent,
          ),
          alignment: Alignment.center,
          child: DefaultTextStyle(
            style: TextStyle(fontSize: 18, color: Colors.black87),
            child: SingleChildScrollView(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  SizedBox(
                    height: 10,
                  ),
                  GestureDetector(
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                      child: Text("Tap to close")),
                  SizedBox(
                    height: 10,
                  ),
                  Divider(
                    height: 4,
                  ),
                  SizedBox(
                    height: 10,
                  ),
                  GestureDetector(
                      onTap: () {
                        print("hello2");
                        //Navigator.of(context).pop();
                      },
                      child: Text("Tap to print")),
                  SizedBox(
                    height: 10,
                  ),
                  Text("Some Text"),
                  SizedBox(
                    height: 10,
                  ),
                  Text("Some Text"),
                  SizedBox(
                    height: 10,
                  ),
                  Text("Some Text"),
                ],
              ),
            ),
          ),
        ),
      );
    };
  }
}

更多关于Flutter对话框对齐插件align_dialog的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter对话框对齐插件align_dialog的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,align_dialog 是一个用于在 Flutter 中自定义对话框位置的插件。虽然它不是 Flutter 官方提供的组件,但在需要特定对齐方式的对话框时非常有用。以下是如何在 Flutter 项目中使用 align_dialog 插件的示例代码。

首先,你需要在 pubspec.yaml 文件中添加 align_dialog 依赖项:

dependencies:
  flutter:
    sdk: flutter
  align_dialog: ^最新版本号  # 请替换为实际的最新版本号

然后运行 flutter pub get 来获取依赖项。

以下是一个简单的示例,展示如何使用 AlignDialog 来创建一个居中对齐的对话框:

import 'package:flutter/material.dart';
import 'package:align_dialog/align_dialog.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Align Dialog Demo'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () => showAlignDialog(context),
            child: Text('Show Align Dialog'),
          ),
        ),
      ),
    );
  }

  void showAlignDialog(BuildContext context) {
    AlignDialog.show(
      context: context,
      builder: (context) {
        return Material(
          type: MaterialType.transparency,
          child: Container(
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(12.0),
            ),
            padding: EdgeInsets.all(16.0),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Text('This is a custom aligned dialog!'),
                SizedBox(height: 16.0),
                ElevatedButton(
                  onPressed: () => Navigator.of(context).pop(),
                  child: Text('Close'),
                ),
              ],
            ),
          ),
        );
      },
      alignment: Alignment.center,  // 这里设置对话框的对齐方式,比如居中
      barrierDismissible: true,
      barrierColor: Colors.black.withOpacity(0.5),
    );
  }
}

在这个示例中,我们做了以下事情:

  1. pubspec.yaml 文件中添加了 align_dialog 依赖项。
  2. 创建了一个简单的 Flutter 应用,其中包含一个按钮,用于触发对话框的显示。
  3. 使用 AlignDialog.show 方法来显示对话框,并设置了 alignment 属性为 Alignment.center 以使对话框居中显示。
  4. 对话框的内容是一个简单的 Column,包含一个文本和一个关闭按钮。

你可以根据需要调整 alignment 属性来设置对话框的对齐方式,例如 Alignment.topLeftAlignment.bottomRight 等。

请确保你已经正确安装了 align_dialog 插件,并且使用的版本与你的 Flutter 环境兼容。如果插件有任何更新或 API 变更,请参考最新的官方文档或 GitHub 仓库。

回到顶部