dialog_content_wrap.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import 'package:cs_resources/generated/assets.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:cs_resources/generated/l10n.dart';
  4. import 'package:flutter_hooks/flutter_hooks.dart';
  5. import 'package:hooks_riverpod/hooks_riverpod.dart';
  6. import 'package:shared/utils/log_utils.dart';
  7. import 'package:widgets/ext/ex_widget.dart';
  8. import 'package:cs_resources/theme/app_colors_theme.dart';
  9. import 'package:widgets/my_text_view.dart';
  10. import 'package:widgets/no_shadow_scroll_behavior.dart';
  11. import 'package:widgets/widget_export.dart';
  12. import '../load_state_layout.dart';
  13. import '../my_load_image.dart';
  14. ///四种视图状态
  15. // enum DialogLoadingState { State_Success, State_Error, State_Loading, State_Empty }
  16. /*
  17. * 弹窗内容的包装组件
  18. * 弹框内容自定义传入 messageBuilder
  19. */
  20. class DialogContentWrap extends StatefulWidget {
  21. LoadState? loadingState;
  22. String? title;
  23. Widget Function(BuildContext)? titleBuilder;
  24. String? message;
  25. Widget Function(BuildContext)? messageBuilder;
  26. VoidCallback confirmAction;
  27. VoidCallback? cancelAction;
  28. bool isShowConfirmBtn;
  29. bool isShowCancelBtn;
  30. Widget Function(BuildContext)? bottomFooterBuilder; // 自定义底部按钮区
  31. bool showCloseIcon;
  32. String? confirmTxt;
  33. String? cancelTxt;
  34. TextStyle? titleTextStyle;
  35. Color? titleBackgroundColor;
  36. Color? backgroundColor;
  37. Color? noBtnBg;
  38. Color? yesBtnBg;
  39. Color? closeIconColor;
  40. TextStyle? yesBtnTextStyle;
  41. TextStyle? noBtnTextStyle;
  42. double? bottomBtnRadius;
  43. EdgeInsets? bottomBtnSectionPadding;
  44. EdgeInsets? contentPadding;
  45. final double? bottomBtnSpace;
  46. final double? topLeftRadius;
  47. final double? topRightRadius;
  48. final double? bottomRightRadius;
  49. final double? bottomLeftRadius;
  50. final double? minHeight;
  51. final double? maxHeight;
  52. final double? dialogWidth;
  53. DialogContentWrap({
  54. Key? key,
  55. this.loadingState = LoadState.State_Loading,
  56. this.title,
  57. this.message,
  58. Widget Function(BuildContext)? this.titleBuilder,
  59. Widget Function(BuildContext)? this.messageBuilder,
  60. Widget Function(BuildContext)? this.bottomFooterBuilder,
  61. required this.confirmAction,
  62. this.cancelAction,
  63. this.showCloseIcon = true,
  64. this.isShowConfirmBtn = true,
  65. this.isShowCancelBtn = true,
  66. this.confirmTxt,
  67. this.cancelTxt,
  68. this.titleTextStyle,
  69. this.titleBackgroundColor = Colors.white,
  70. this.backgroundColor = Colors.white,
  71. this.closeIconColor = Colors.white,
  72. this.bottomBtnRadius = 7,
  73. this.noBtnBg,
  74. this.yesBtnBg,
  75. this.yesBtnTextStyle,
  76. this.noBtnTextStyle,
  77. this.bottomBtnSectionPadding,
  78. this.contentPadding = const EdgeInsets.only(
  79. left: 0, right: 0, bottom: 0, top: 0),
  80. this.bottomBtnSpace = 0,
  81. topLeftRadius,
  82. topRightRadius,
  83. bottomLeftRadius,
  84. bottomRightRadius,
  85. minHeight,
  86. maxHeight,
  87. dialogWidth,
  88. })
  89. : minHeight = minHeight ?? 0,
  90. maxHeight = maxHeight ?? 300,
  91. dialogWidth = dialogWidth ?? 300.0,
  92. topLeftRadius = topLeftRadius ?? 0,
  93. topRightRadius = topRightRadius ?? 0,
  94. bottomLeftRadius = bottomLeftRadius ?? 0,
  95. bottomRightRadius = bottomRightRadius ?? 0,
  96. super(key: key);
  97. @override
  98. DialogContentWrapState createState() => DialogContentWrapState();
  99. }
  100. class DialogContentWrapState extends State<DialogContentWrap> {
  101. @override
  102. void initState() {
  103. super.initState();
  104. }
  105. // 修改 dialogLoadingState
  106. void changeDialogLoadingState(LoadState state){
  107. Log.d("change loadState");
  108. setState(() {
  109. widget.loadingState = state;
  110. });
  111. }
  112. @override
  113. Widget build(BuildContext context) {
  114. Log.d("dialogWidth ${widget.dialogWidth} ");
  115. double _dialogWidth = widget.dialogWidth?? MediaQuery.of(context).size.width * 0.65;
  116. bool _showTitleSection = (widget.title != null && widget.title!.isNotEmpty) || widget.titleBuilder != null;
  117. bool _showBottomBtnSection = widget.isShowConfirmBtn || widget.isShowCancelBtn || widget.bottomFooterBuilder != null;
  118. double _bottomBtnSectionHeight = _showBottomBtnSection ? 50 : 0;
  119. double _scrollMaxHeight = widget.maxHeight! - _bottomBtnSectionHeight;
  120. double _bottomBtnMargin = 0;
  121. String _errorMessage = 'Data loading failed! Please refresh and try again';
  122. if(widget.isShowConfirmBtn && widget.isShowCancelBtn){
  123. _bottomBtnMargin = widget.bottomBtnSpace??0/2;
  124. }
  125. return Stack(
  126. children: [
  127. ClipRRect(
  128. borderRadius: BorderRadius.only(
  129. topLeft: Radius.circular(widget.topLeftRadius!),
  130. topRight: Radius.circular(widget.topRightRadius!),
  131. bottomLeft: Radius.circular(widget.bottomLeftRadius!),
  132. bottomRight: Radius.circular(widget.bottomRightRadius!),
  133. ),
  134. child: Container(
  135. width: _dialogWidth,
  136. constraints: BoxConstraints(
  137. minHeight: widget.minHeight!,
  138. maxHeight: widget.maxHeight!,
  139. ),
  140. decoration: BoxDecoration(
  141. color: widget.backgroundColor?? context.appColors.whiteBG,
  142. // borderRadius: BorderRadius.only(
  143. // topLeft: Radius.circular(topLeftRadius!),
  144. // topRight: Radius.circular(topRightRadius!),
  145. // ),
  146. ),
  147. child: LoadStateLayout(
  148. state: widget.loadingState??LoadState.State_Loading,
  149. errorMessage: _errorMessage,
  150. errorRetry: () {
  151. },
  152. successWidget: Column(
  153. children: [
  154. // 标题区
  155. Container(
  156. width: double.infinity,
  157. color: widget.titleBackgroundColor,
  158. child: Visibility(
  159. visible: _showTitleSection,
  160. child: (widget.title != null && widget.title!.isNotEmpty)? MyTextView(
  161. widget.title ?? '',
  162. fontSize: 18,
  163. isFontMedium: true,
  164. textColor: widget.titleTextStyle?.color ?? context.appColors.textBlack,
  165. paddingTop: 15,
  166. paddingBottom: 15,
  167. textAlign: TextAlign.center,
  168. textStyle: widget.titleTextStyle,
  169. ): widget.titleBuilder!.call(context),
  170. ),
  171. ),
  172. // 内容区
  173. Expanded(
  174. child: Scrollbar(
  175. child: ScrollConfiguration(
  176. behavior: NoShadowScrollBehavior(),
  177. child: SingleChildScrollView(
  178. child: Container(
  179. width: double.infinity,
  180. padding: widget.contentPadding,
  181. child: widget.messageBuilder?.call(context) ??
  182. MyTextView(
  183. widget.message!,
  184. fontSize: 18,
  185. textColor: context.appColors.textBlack,
  186. isFontRegular: true,
  187. textAlign: TextAlign.center,
  188. ),
  189. ),
  190. ),
  191. ),
  192. ).constrained(maxHeight: _scrollMaxHeight),
  193. ),
  194. // 底部按钮区
  195. Visibility(
  196. visible: _showBottomBtnSection,
  197. child: (widget.isShowCancelBtn || widget.isShowConfirmBtn)? Container(
  198. height: _bottomBtnSectionHeight,
  199. color: context.appColors.whiteBG,
  200. padding: widget.bottomBtnSectionPadding,
  201. child: Row(
  202. mainAxisAlignment: MainAxisAlignment.center,
  203. children: [
  204. Visibility(
  205. visible: widget.isShowCancelBtn,
  206. child: Expanded(
  207. flex: 1,
  208. child: InkWell(
  209. onTap: () {
  210. onCancel();
  211. widget.cancelAction?.call();
  212. },
  213. child: MyTextView(
  214. widget.cancelTxt ?? S.current.no,
  215. fontSize: 16,
  216. isFontMedium: true,
  217. paddingTop: 13,
  218. paddingBottom: 13,
  219. textAlign: TextAlign.center,
  220. textColor: context.appColors.whiteBG,
  221. backgroundColor: widget.noBtnBg ?? context.appColors.orangeBG,
  222. cornerRadius: widget.bottomBtnRadius ?? 0,
  223. textStyle: widget.noBtnTextStyle,
  224. ),
  225. )),
  226. ),
  227. SizedBox(
  228. width: _bottomBtnMargin,
  229. ),
  230. Visibility(
  231. visible: widget.isShowConfirmBtn,
  232. child: Expanded(
  233. flex: 1,
  234. child: InkWell(
  235. onTap: () async {
  236. onCancel();
  237. widget.confirmAction();
  238. },
  239. child: MyTextView(
  240. widget.confirmTxt ?? S.current.yes,
  241. fontSize: 16,
  242. paddingTop: 13,
  243. paddingBottom: 13,
  244. isFontMedium: true,
  245. textAlign: TextAlign.center,
  246. textColor: Colors.white,
  247. backgroundColor: widget.yesBtnBg?? context.appColors.btnBgDefault,
  248. cornerRadius: widget.bottomBtnRadius ?? 0,
  249. textStyle: widget.yesBtnTextStyle,
  250. ),
  251. )),
  252. ),
  253. ],
  254. ),
  255. ): Container(
  256. child: widget.bottomFooterBuilder?.call(context),
  257. ),
  258. ),
  259. ],
  260. ),
  261. ),
  262. ),
  263. ),
  264. // 右上角 关闭按钮
  265. Visibility(
  266. visible: widget.showCloseIcon,
  267. child: Positioned(
  268. top: 0,
  269. right: 0,
  270. child: MyAssetImage(
  271. Assets.baseServiceDialogDeleteIcon,
  272. width: 25,
  273. height: 25.5,
  274. color: widget.closeIconColor ?? context.appColors.textPrimary,
  275. ).onTap((){
  276. onCancel();
  277. },padding: 10),
  278. ),
  279. )
  280. ],
  281. );
  282. }
  283. //取消弹框
  284. void onCancel() async {
  285. SmartDialog.dismiss();
  286. }
  287. }