alert_dialog.dart 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. class VAlertDialog extends StatelessWidget {
  4. /// 标题
  5. final String? title;
  6. /// 内容
  7. final Widget content;
  8. /// 内容内距
  9. final EdgeInsetsGeometry? contentPadding;
  10. /// 宽度
  11. final double width;
  12. /// 确定按钮文本
  13. final String confirmLabel;
  14. /// 取消按钮文本
  15. final String cancelLabel;
  16. /// 取消回调
  17. final VoidCallback? onCanceled;
  18. /// 确定回调,不为空则显示确定按钮
  19. final VoidCallback? onConfirm;
  20. /// 是否显示取消按钮
  21. final bool showCancel;
  22. const VAlertDialog({
  23. super.key,
  24. this.title,
  25. required this.content,
  26. this.contentPadding,
  27. this.width = 460,
  28. this.confirmLabel = "确定",
  29. this.cancelLabel = "取消",
  30. this.onCanceled,
  31. this.onConfirm,
  32. this.showCancel = true,
  33. });
  34. static Future<T?> showDialog<T>(
  35. Widget child, [
  36. bool barrierDismissible = false,
  37. ]) async {
  38. return await Get.dialog<T>(
  39. child,
  40. barrierDismissible: barrierDismissible,
  41. barrierColor: Colors.black.withOpacity(.4),
  42. );
  43. }
  44. @override
  45. Widget build(BuildContext context) {
  46. final actions = _buildActions(context);
  47. final hasActions = actions != null && actions.length > 1;
  48. return AlertDialog(
  49. backgroundColor: Colors.white,
  50. elevation: 0,
  51. title: title != null ? Text(title!) : null,
  52. titleTextStyle: const TextStyle(fontSize: 24, color: Colors.black),
  53. actionsAlignment:
  54. hasActions ? MainAxisAlignment.spaceAround : MainAxisAlignment.center,
  55. actions: actions,
  56. contentPadding:
  57. contentPadding ?? const EdgeInsets.only(top: 20, bottom: 8),
  58. content: SizedBox(
  59. width: width,
  60. child: content,
  61. ),
  62. );
  63. }
  64. List<Widget>? _buildActions(BuildContext context) {
  65. final widgets = <Widget>[];
  66. final showConfirm = onConfirm != null;
  67. double btnWidth = 0;
  68. if (showCancel && showConfirm) {
  69. btnWidth = (width - 20) / 2;
  70. } else {
  71. if (showCancel || showConfirm) {
  72. btnWidth = width - 12;
  73. }
  74. }
  75. if (showCancel) {
  76. widgets.add(
  77. _AlertActionButton(
  78. width: btnWidth,
  79. label: cancelLabel,
  80. onPressed: () {
  81. Navigator.of(context).pop();
  82. onCanceled?.call();
  83. },
  84. ),
  85. );
  86. }
  87. if (showConfirm) {
  88. if (widgets.isNotEmpty) {
  89. widgets.add(
  90. SizedBox(
  91. height: 24,
  92. child: VerticalDivider(
  93. thickness: 1,
  94. color: Colors.black.withOpacity(.4),
  95. ),
  96. ),
  97. );
  98. }
  99. widgets.add(
  100. _AlertActionButton(
  101. width: btnWidth,
  102. label: confirmLabel,
  103. onPressed: () {
  104. onConfirm!.call();
  105. },
  106. ),
  107. );
  108. }
  109. return widgets;
  110. }
  111. }
  112. class _AlertActionButton extends StatelessWidget {
  113. final String label;
  114. final double width;
  115. final VoidCallback onPressed;
  116. const _AlertActionButton({
  117. super.key,
  118. required this.label,
  119. required this.onPressed,
  120. required this.width,
  121. });
  122. @override
  123. Widget build(BuildContext context) {
  124. return SizedBox(
  125. width: width,
  126. height: 48,
  127. child: TextButton(
  128. onPressed: onPressed,
  129. child: Text(
  130. label,
  131. style: const TextStyle(fontSize: 18),
  132. ),
  133. ),
  134. );
  135. }
  136. }