loading_dialog.dart 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import 'package:flutter/material.dart';
  2. import 'package:tdesign_flutter/tdesign_flutter.dart';
  3. import '../../core/i18n/app_localizations.dart';
  4. import '../../core/theme/app_colors_extension.dart';
  5. /// 通用 loading 弹窗。
  6. ///
  7. /// 深灰色半透明蒙版,居中 loading 动画 + 可自定义文本。
  8. /// 蒙版透明但不可点击穿透。
  9. ///
  10. /// 使用方式:
  11. /// ```dart
  12. /// LoadingDialog.show(context, text: '数据加载中...');
  13. /// // ... 异步操作 ...
  14. /// LoadingDialog.hide(context);
  15. /// ```
  16. class LoadingDialog {
  17. LoadingDialog._();
  18. /// 显示 loading 弹窗。[text] 默认为 i18n "loading"(加载中…)。
  19. static void show(BuildContext context, {String? text}) {
  20. showDialog(
  21. context: context,
  22. barrierColor: Colors.transparent,
  23. barrierDismissible: false,
  24. builder: (_) => _LoadingContent(text: text),
  25. );
  26. }
  27. /// 关闭 loading 弹窗。即使弹窗已被关闭也不会抛异常。
  28. /// 使用 rootNavigator 匹配 showDialog 默认的 useRootNavigator: true。
  29. static void hide(BuildContext context) {
  30. Navigator.of(context, rootNavigator: true).maybePop();
  31. }
  32. }
  33. class _LoadingContent extends StatelessWidget {
  34. final String? text;
  35. const _LoadingContent({this.text});
  36. @override
  37. Widget build(BuildContext context) {
  38. final l10n = AppLocalizations.of(context);
  39. final colors = Theme.of(context).extension<AppColorsExtension>()!;
  40. return Center(
  41. child: Container(
  42. constraints: const BoxConstraints(minWidth: 120, maxWidth: 220),
  43. padding: const EdgeInsets.fromLTRB(16, 24, 16, 20),
  44. decoration: BoxDecoration(
  45. color: colors.loadingCard,
  46. borderRadius: BorderRadius.circular(12),
  47. ),
  48. child: Column(
  49. mainAxisSize: MainAxisSize.min,
  50. children: [
  51. IconTheme(
  52. data: const IconThemeData(color: Colors.white),
  53. child: const TDLoading(
  54. size: TDLoadingSize.large,
  55. icon: TDLoadingIcon.activity,
  56. ),
  57. ),
  58. const SizedBox(height: 14),
  59. Text(
  60. text ?? l10n.get('loading'),
  61. textAlign: TextAlign.center,
  62. softWrap: true,
  63. style: const TextStyle(
  64. fontSize: 14,
  65. fontWeight: FontWeight.w500,
  66. color: Colors.white,
  67. ),
  68. ),
  69. ],
  70. ),
  71. ),
  72. );
  73. }
  74. }