Flutter对话框插件dh_dialog的使用

Flutter对话框插件dh_dialog的使用

dh_dialog 插件支持多种类型的对话框,包括 AlertDialogListDialogChoiceDialogGridDialogInputDialog。如果上述类型不能满足需求,还可以通过自定义 DHDialog 来实现。

显示对话框

使用 showDHDialog 方法来显示对话框:

Future<T?> showDHDialog<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  RouteTransitionsBuilder? transitionBuilder,
  EntryAnimation entryAnimation = EntryAnimation.none,
  Duration? transitionDuration,
  Color barrierColor = Colors.black54,
  bool barrierDismissible = true,
  bool useSafeArea = true,
  bool useRootNavigator = true,
});
  • entryAnimation 参数用于控制进入动画,已经支持滑动和淡入淡出动画。

关闭对话框

使用 dismissDHDialog 方法关闭对话框:

dismissDHDialog(context);

AlertDialog 示例

DHAlertDialog 是一个简单的对话框,带有标题和内容:

DHAlertDialog(
  titleText: "Title",
  contentText: "Content",
  hasPositive: true, // 是否显示确认按钮
  hasNegative: false, // 是否显示取消按钮
  positiveTap: () => dismissDHDialog(context), // 点击确认后的回调
)

alert_dialog

ListDialog 示例

DHListDialog 是一个列表型对话框,可以用来展示多个选项:

DHListDialog(
  titleText: "班级",
  titleAlign: TextAlign.center,
  hasTitleDivider: true,
  datas: [
    DialogListItem(TextItem(text: "高一(1)班"), data: "1"),
    DialogListItem(TextItem(text: "高一(2)班"), data: "2"),
    DialogListItem(TextItem(text: "高一(3)班"), data: "3"),
  ],
  itemAlignment: Alignment.centerLeft,
  itemClickListener: (data, position, context) {
    print('data: $data, position: $position');
    dismissDHDialog(context);
  },
  dividerColor: Colors.yellow,
  itemDividerBuilder: (context, index) => Container(
    color: Colors.red,
    height: 1.0,
  ),
  hasNegative: false,
  hasPositive: false,
  actionDividerBuilder: (context, type) {
    return Container(
      color: Colors.purple,
      height: type == DividerType.horizontal ? 1.0 : null,
      width: type == DividerType.vertical ? 1.0 : null,
    );
  },
  contentPadding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
  dialogMargin: EdgeInsets.zero,
  bottomRadius: 0,
  topRadius: 10,
);

list_dialog

ChoiceDialog 示例

DHChoiceDialog 是一个多选或单选对话框:

单选示例

List<DialogListItem<ChoiceItem, String>> weeks = [
  DialogListItem(
      ChoiceItem(
          imgWidth: 22,
          imgHeight: 22,
          text: Selector.all("星期天"),
          image: Selector.normal(
              normal: '$imagePathPrefix/check_nor.png',
              active: '$imagePathPrefix/check_sel.png'),
          selected: false),
      data: "0"),
  DialogListItem(
      ChoiceItem(
          imgWidth: 22,
          imgHeight: 22,
          text: Selector.all("星期一"),
          image: Selector.normal(
              normal: '$imagePathPrefix/check_nor.png',
              active: '$imagePathPrefix/check_sel.png'),
          selected: false),
      data: "1"),
  // 其他选项...
];

DHChoiceDialog<ChoiceItem, String>(
  titleText: "星期单选",
  itemAlignment: Alignment.centerLeft,
  datas: weeks,
  multiChose: false, // 设置为 false 表示单选
  titleDivider: Divider(height: 10, color: Colors.orange),
);

single_choice_dialog

多选示例

multiChose 设置为 true 即可实现多选:

DHChoiceDialog<ChoiceItem, String>(
  titleText: "星期多选",
  itemAlignment: Alignment.centerLeft,
  datas: weeks,
  multiChose: true,
);

multi_choice_dialog

GridDialog 示例

DHGridDialog 是一个网格型对话框,适合展示多个选项:

var datas = [
  TextItem(text: '选项1'),
  TextItem(text: '选项2'),
  TextItem(text: '选项3'),
  TextItem(text: '选项4'),
  TextItem(text: '选项5'),
  TextItem(text: '选项6'),
  TextItem(text: '选项7'),
  TextItem(text: '选项8'),
  TextItem(text: '选项9'),
].mapIndexed((index, e) => DialogListItem(e, data: index))
.toList();

DHGridDialog(
  bottomRadius: .0,
  topRadius: 10.0,
  hasNegative: false,
  hasPositive: false,
  dialogAlignment: Alignment.bottomCenter,
  dialogMargin: EdgeInsets.zero,
  titleText: '网格列表',
  itemClickListener: (int? data, int position, BuildContext context) {
    print('click item $position');
  },
  datas: datas,
  itemBuilder: (
    BuildContext context,
    TextItem data,
    int index, {
    BorderRadius? borderRadius,
    EdgeInsetsGeometry? padding,
    double? height,
    AlignmentGeometry? alignment,
    GestureTapCallback? onTap,
  }) {
    return GestureDetector(
      onTap: onTap,
      behavior: HitTestBehavior.opaque,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            padding: EdgeInsets.all(14.0),
            decoration: ShapeDecoration(
              color: Color(0xFFF5F7FA),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(16.0)),
              ),
            ),
            child: Image.asset(
              '$imagePathPrefix/default_icon.png',
              width: 20,
              height: 22,
            ),
          ),
          SizedBox(height: 8.0),
          Text(data.text, style: data.textStyle),
        ],
      ),
    );
  },
  crossAxisCount: 4,
  childAspectRatio: 0.76,
  contentPadding: EdgeInsets.only(
    left: 10.0,
    right: 10.0,
    bottom: MediaQuery.of(context).padding.bottom,
  ),
);

grid_dialog

InputDialog 示例

DHInputDialog 是一个带输入框的对话框:

showDHDialog(
  entryAnimation: EntryAnimation.slideBottom,
  context: context,
  builder: (context) {
    TextEditingController? editController;
    var getter = (controller) => editController = controller;

    return DHInputDialog(
      titleText: "输入对话框",
      filled: true,
      style: TextStyle(color: Colors.black, fontSize: 15),
      borderStyle: InputBorderStyle.outline,
      controllerGetter: getter,
      keyboardType: TextInputType.number,
      hintText: "请输入用户名",
      suffixOnTap: () => editController?.text = "",
      suffix: Text(
        "删除",
        style: TextStyle(color: Colors.pink, fontSize: 12),
      ),
      positiveTap: (result) {
        dismissDHDialog(context);
      },
      negativeTap: (result) {
        dismissDHDialog(context);
      },
    );
  },
);

input_dialog

完整示例代码

以下是一个完整的示例代码,展示了如何使用 dh_dialog 插件的各种对话框类型:

import 'package:collection/collection.dart';
import 'package:dh_dialog/dh_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.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,
        useMaterial3: false,
        scaffoldBackgroundColor: Colors.amber,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: '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) {
    List<DialogListItem<ChoiceItem, String>> weeks = [
      DialogListItem(
          ChoiceItem(
              imgWidth: 22,
              imgHeight: 22,
              text: Selector.all("星期天"),
              image: Selector.normal(
                  normal: '$imagePathPrefix/check_nor.png',
                  active: '$imagePathPrefix/check_sel.png'),
              selected: false),
          data: "0"),
      // 其他选项...
    ];

    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              onPressed: () {
                showDHDialog(
                  context: context,
                  builder: (context) {
                    return DHAlertDialog(
                      titleText: "Title",
                      contentText: "Content",
                      hasPositive: true,
                      hasNegative: false,
                      positiveTap: () => dismissDHDialog(context),
                    );
                  },
                  entryAnimation: EntryAnimation.slideBottom,
                );
              },
              child: Text("AlertDialog"),
            ),
            TextButton(
              onPressed: () {
                showDHDialog(
                  entryAnimation: EntryAnimation.slideBottom,
                  context: context,
                  builder: (context) {
                    return DHListDialog(
                      titleText: "班级",
                      titleAlign: TextAlign.center,
                      hasTitleDivider: true,
                      datas: [
                        DialogListItem(TextItem(text: "高一(1)班"), data: "1"),
                        DialogListItem(TextItem(text: "高一(2)班"), data: "2"),
                        DialogListItem(TextItem(text: "高一(3)班"), data: "3"),
                      ],
                      itemAlignment: Alignment.centerLeft,
                      itemClickListener: (data, position, context) {
                        print('data: $data, position: $position');
                        dismissDHDialog(context);
                      },
                      dividerColor: Colors.yellow,
                      itemDividerBuilder: (context, index) => Container(
                        color: Colors.red,
                        height: 1.0,
                      ),
                      hasNegative: false,
                      hasPositive: false,
                      actionDividerBuilder: (context, type) {
                        return Container(
                          color: Colors.purple,
                          height: type == DividerType.horizontal ? 1.0 : null,
                          width: type == DividerType.vertical ? 1.0 : null,
                        );
                      },
                      contentPadding: EdgeInsets.only(
                          bottom: MediaQuery.of(context).padding.bottom),
                      dialogMargin: EdgeInsets.zero,
                      bottomRadius: 0,
                      topRadius: 10,
                    );
                  },
                );
              },
              child: Text("ListDialog"),
            ),
            TextButton(
              onPressed: () {
                showDHDialog(
                  entryAnimation: EntryAnimation.slideBottom,
                  context: context,
                  builder: (context) {
                    return DHChoiceDialog<ChoiceItem, String>(
                      titleText: "星期单选",
                      itemAlignment: Alignment.centerLeft,
                      datas: weeks,
                      multiChose: false,
                      titleDivider: Divider(height: 10, color: Colors.orange),
                    );
                  },
                );
              },
              child: Text("SingleChoiceDialog"),
            ),
            TextButton(
              onPressed: () {
                showDHDialog(
                  entryAnimation: EntryAnimation.slideBottom,
                  context: context,
                  builder: (context) {
                    return DHChoiceDialog<ChoiceItem, String>(
                      titleText: "星期多选",
                      itemAlignment: Alignment.centerLeft,
                      datas: weeks,
                      multiChose: true,
                    );
                  },
                );
              },
              child: Text("MultipleChoiceDialog"),
            ),
            TextButton(
              onPressed: () {
                showDHDialog(
                  entryAnimation: EntryAnimation.slideBottom,
                  context: context,
                  builder: (context) {
                    TextEditingController? editController;
                    var getter = (controller) => editController = controller;

                    return DHInputDialog(
                      titleText: "输入对话框",
                      filled: true,
                      style: TextStyle(color: Colors.black, fontSize: 15),
                      borderStyle: InputBorderStyle.outline,
                      controllerGetter: getter,
                      keyboardType: TextInputType.number,
                      hintText: "请输入用户名",
                      suffixOnTap: () => editController?.text = "",
                      suffix: Text(
                        "删除",
                        style: TextStyle(color: Colors.pink, fontSize: 12),
                      ),
                      positiveTap: (result) {
                        dismissDHDialog(context);
                      },
                      negativeTap: (result) {
                        dismissDHDialog(context);
                      },
                    );
                  },
                );
              },
              child: Text("InputDialog"),
            ),
            TextButton(
              onPressed: () {
                showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    var datas = [
                      TextItem(text: '选项1'),
                      TextItem(text: '选项2'),
                      TextItem(text: '选项3'),
                      TextItem(text: '选项4'),
                      TextItem(text: '选项5'),
                      TextItem(text: '选项6'),
                      TextItem(text: '选项7'),
                      TextItem(text: '选项8'),
                      TextItem(text: '选项9'),
                    ].mapIndexed((index, e) => DialogListItem(e, data: index)).toList();

                    return DHGridDialog(
                      bottomRadius: .0,
                      topRadius: 10.0,
                      hasNegative: false,
                      hasPositive: false,
                      dialogAlignment: Alignment.bottomCenter,
                      dialogMargin: EdgeInsets.zero,
                      titleText: '网格列表',
                      itemClickListener: (int? data, int position, BuildContext context) {
                        print('click item $position');
                      },
                      datas: datas,
                      itemBuilder: (
                        BuildContext context,
                        TextItem data,
                        int index, {
                        BorderRadius? borderRadius,
                        EdgeInsetsGeometry? padding,
                        double? height,
                        AlignmentGeometry? alignment,
                        GestureTapCallback? onTap,
                      }) {
                        return GestureDetector(
                          onTap: onTap,
                          behavior: HitTestBehavior.opaque,
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Container(
                                padding: EdgeInsets.all(14.0),
                                decoration: ShapeDecoration(
                                  color: Color(0xFFF5F7FA),
                                  shape: RoundedRectangleBorder(
                                    borderRadius: BorderRadius.all(Radius.circular(16.0)),
                                  ),
                                ),
                                child: Image.asset(
                                  '$imagePathPrefix/default_icon.png',
                                  width: 20,
                                  height: 22,
                                ),
                              ),
                              SizedBox(height: 8.0),
                              Text(data.text, style: data.textStyle),
                            ],
                          ),
                        );
                      },
                      crossAxisCount: 4,
                      childAspectRatio: 0.76,
                      contentPadding: EdgeInsets.only(
                        left: 10.0,
                        right: 10.0,
                        bottom: MediaQuery.of(context).padding.bottom,
                      ),
                    );
                  },
                );
              },
              child: Text('GridDialog'),
            ),
          ],
        ),
      ),
    );
  }
}

const String imagePathPrefix = "assets/images";

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

1 回复

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


dh_dialog 是一个 Flutter 插件,用于简化对话框的创建和管理。它提供了多种类型的对话框,如确认对话框、提示对话框、加载对话框等。以下是如何使用 dh_dialog 插件的步骤:

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 dh_dialog 依赖:

dependencies:
  flutter:
    sdk: flutter
  dh_dialog: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

2. 导入包

在你的 Dart 文件中导入 dh_dialog 包:

import 'package:dh_dialog/dh_dialog.dart';

3. 使用 dh_dialog

3.1 显示确认对话框

确认对话框通常用于让用户确认某个操作,比如删除操作。

DhDialog.confirm(
  context,
  title: "确认删除",
  content: "你确定要删除这条记录吗?",
  onConfirm: () {
    // 用户点击确认后的操作
    print("确认删除");
  },
  onCancel: () {
    // 用户点击取消后的操作
    print("取消删除");
  },
);

3.2 显示提示对话框

提示对话框通常用于显示一些信息给用户。

DhDialog.alert(
  context,
  title: "提示",
  content: "操作成功!",
  onConfirm: () {
    // 用户点击确认后的操作
    print("确认提示");
  },
);

3.3 显示加载对话框

加载对话框通常用于在后台执行耗时操作时显示给用户。

DhDialog.loading(
  context,
  message: "正在加载...",
);

// 模拟耗时操作
Future.delayed(Duration(seconds: 2), () {
  // 关闭加载对话框
  Navigator.of(context).pop();
});

3.4 显示自定义对话框

如果你想显示一个自定义的对话框,可以使用 DhDialog.custom

DhDialog.custom(
  context,
  builder: (context) {
    return AlertDialog(
      title: Text("自定义对话框"),
      content: Text("这是一个自定义对话框。"),
      actions: [
        TextButton(
          onPressed: () {
            Navigator.of(context).pop();
          },
          child: Text("关闭"),
        ),
      ],
    );
  },
);

4. 其他功能

dh_dialog 还提供了其他一些功能,比如设置对话框的样式、按钮文本等。你可以查看插件的文档或源代码来了解更多细节。

5. 注意事项

  • 确保在使用 dh_dialog 时,context 是有效的,通常是在 build 方法中使用。
  • 在显示加载对话框时,记得在操作完成后关闭对话框,否则对话框会一直显示。

6. 示例代码

以下是一个完整的示例代码,展示了如何使用 dh_dialog 插件:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("dh_dialog 示例"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                DhDialog.confirm(
                  context,
                  title: "确认删除",
                  content: "你确定要删除这条记录吗?",
                  onConfirm: () {
                    print("确认删除");
                  },
                  onCancel: () {
                    print("取消删除");
                  },
                );
              },
              child: Text("显示确认对话框"),
            ),
            ElevatedButton(
              onPressed: () {
                DhDialog.alert(
                  context,
                  title: "提示",
                  content: "操作成功!",
                  onConfirm: () {
                    print("确认提示");
                  },
                );
              },
              child: Text("显示提示对话框"),
            ),
            ElevatedButton(
              onPressed: () {
                DhDialog.loading(
                  context,
                  message: "正在加载...",
                );

                Future.delayed(Duration(seconds: 2), () {
                  Navigator.of(context).pop();
                });
              },
              child: Text("显示加载对话框"),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部