dialog_content_wrap.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. TextStyle? yesBtnTextStyle;
  40. TextStyle? noBtnTextStyle;
  41. double? bottomBtnRadius;
  42. EdgeInsets? bottomBtnSectionPadding;
  43. EdgeInsets? contentPadding;
  44. final double? bottomBtnSpace;
  45. final double? topLeftRadius;
  46. final double? topRightRadius;
  47. final double? minHeight;
  48. final double? maxHeight;
  49. DialogContentWrap({
  50. Key? key,
  51. this.loadingState = LoadState.State_Loading,
  52. this.title,
  53. this.message,
  54. Widget Function(BuildContext)? this.titleBuilder,
  55. Widget Function(BuildContext)? this.messageBuilder,
  56. Widget Function(BuildContext)? this.bottomFooterBuilder,
  57. required this.confirmAction,
  58. this.cancelAction,
  59. this.showCloseIcon = true,
  60. this.isShowConfirmBtn = true,
  61. this.isShowCancelBtn = true,
  62. this.confirmTxt,
  63. this.cancelTxt,
  64. this.titleTextStyle,
  65. this.titleBackgroundColor = Colors.white,
  66. this.backgroundColor = Colors.white,
  67. this.bottomBtnRadius = 7,
  68. this.noBtnBg,
  69. this.yesBtnBg,
  70. this.yesBtnTextStyle,
  71. this.noBtnTextStyle,
  72. this.bottomBtnSectionPadding,
  73. this.contentPadding = const EdgeInsets.only(
  74. left: 0, right: 0, bottom: 0, top: 0),
  75. this.bottomBtnSpace = 0,
  76. topLeftRadius,
  77. topRightRadius,
  78. minHeight,
  79. maxHeight,
  80. })
  81. : minHeight = minHeight ?? 0,
  82. maxHeight = maxHeight ?? 300,
  83. topLeftRadius = topLeftRadius ?? 0,
  84. topRightRadius = topRightRadius ?? 0,
  85. super(key: key);
  86. @override
  87. DialogContentWrapState createState() => DialogContentWrapState();
  88. }
  89. class DialogContentWrapState extends State<DialogContentWrap> {
  90. @override
  91. void initState() {
  92. super.initState();
  93. }
  94. // 修改 dialogLoadingState
  95. void changeDialogLoadingState(LoadState state){
  96. Log.d("change loadState");
  97. setState(() {
  98. widget.loadingState = state;
  99. });
  100. }
  101. @override
  102. Widget build(BuildContext context) {
  103. bool _showTitleSection = (widget.title != null && widget.title!.isNotEmpty) || widget.titleBuilder != null;
  104. bool _showBottomBtnSection = widget.isShowConfirmBtn || widget.isShowCancelBtn || widget.bottomFooterBuilder != null;
  105. double _bottomBtnSectionHeight = _showBottomBtnSection ? 50 : 0;
  106. double _scrollMaxHeight = widget.maxHeight! - _bottomBtnSectionHeight;
  107. double _bottomBtnMargin = 0;
  108. String _errorMessage = 'Data loading failed! Please refresh and try again';
  109. if(widget.isShowConfirmBtn && widget.isShowCancelBtn){
  110. _bottomBtnMargin = widget.bottomBtnSpace??0/2;
  111. }
  112. return Stack(children: [
  113. ClipRRect(
  114. borderRadius: BorderRadius.only(
  115. topLeft: Radius.circular(widget.topLeftRadius!),
  116. topRight: Radius.circular(widget.topRightRadius!),
  117. ),
  118. child: Container(
  119. width: double.infinity,
  120. constraints: BoxConstraints(
  121. minHeight: widget.minHeight!,
  122. maxHeight: widget.maxHeight!,
  123. ),
  124. decoration: BoxDecoration(
  125. color: widget.backgroundColor?? context.appColors.whiteBG,
  126. // borderRadius: BorderRadius.only(
  127. // topLeft: Radius.circular(topLeftRadius!),
  128. // topRight: Radius.circular(topRightRadius!),
  129. // ),
  130. ),
  131. child: LoadStateLayout(
  132. state: widget.loadingState??LoadState.State_Loading,
  133. errorMessage: _errorMessage,
  134. errorRetry: () {
  135. },
  136. successWidget: Column(
  137. children: [
  138. // 标题区
  139. Container(
  140. width: double.infinity,
  141. color: widget.titleBackgroundColor,
  142. child: Visibility(
  143. visible: _showTitleSection,
  144. child: (widget.title != null && widget.title!.isNotEmpty)? MyTextView(
  145. widget.title ?? '',
  146. fontSize: 18,
  147. isFontMedium: true,
  148. textColor: context.appColors.textBlack,
  149. paddingTop: 15,
  150. textAlign: TextAlign.center,
  151. textStyle: widget.titleTextStyle,
  152. ): widget.titleBuilder!.call(context),
  153. ),
  154. ),
  155. // 内容区
  156. Expanded(
  157. child: Scrollbar(
  158. child: ScrollConfiguration(
  159. behavior: NoShadowScrollBehavior(),
  160. child: SingleChildScrollView(
  161. child: Container(
  162. padding: widget.contentPadding,
  163. child: widget.messageBuilder?.call(context) ??
  164. MyTextView(
  165. widget.message!,
  166. fontSize: 18,
  167. textColor: context.appColors.textBlack,
  168. isFontRegular: true,
  169. textAlign: TextAlign.center,
  170. ),
  171. ),
  172. ),
  173. ),
  174. ).constrained(maxHeight: _scrollMaxHeight),
  175. ),
  176. // 底部按钮区
  177. Visibility(
  178. visible: _showBottomBtnSection,
  179. child: (widget.isShowCancelBtn || widget.isShowConfirmBtn)? Container(
  180. // height: _bottomBtnSectionHeight,
  181. color: context.appColors.whiteBG,
  182. padding: widget.bottomBtnSectionPadding,
  183. child: Row(
  184. mainAxisAlignment: MainAxisAlignment.center,
  185. children: [
  186. Visibility(
  187. visible: widget.isShowCancelBtn,
  188. child: Expanded(
  189. flex: 1,
  190. child: InkWell(
  191. onTap: () {
  192. onCancel();
  193. widget.cancelAction?.call();
  194. },
  195. child: MyTextView(
  196. widget.cancelTxt ?? S.current.no,
  197. fontSize: 16,
  198. isFontMedium: true,
  199. paddingTop: 13,
  200. paddingBottom: 13,
  201. textAlign: TextAlign.center,
  202. textColor: context.appColors.whiteBG,
  203. backgroundColor: widget.noBtnBg ?? context.appColors.orangeBG,
  204. cornerRadius: widget.bottomBtnRadius ?? 0,
  205. textStyle: widget.noBtnTextStyle,
  206. ),
  207. )),
  208. ),
  209. SizedBox(
  210. width: _bottomBtnMargin,
  211. ),
  212. Visibility(
  213. visible: widget.isShowConfirmBtn,
  214. child: Expanded(
  215. flex: 1,
  216. child: InkWell(
  217. onTap: () async {
  218. onCancel();
  219. widget.confirmAction();
  220. },
  221. child: MyTextView(
  222. widget.confirmTxt ?? S.current.yes,
  223. fontSize: 16,
  224. paddingTop: 13,
  225. paddingBottom: 13,
  226. isFontMedium: true,
  227. textAlign: TextAlign.center,
  228. textColor: Colors.white,
  229. backgroundColor: widget.yesBtnBg?? context.appColors.btnBgDefault,
  230. cornerRadius: widget.bottomBtnRadius ?? 0,
  231. textStyle: widget.yesBtnTextStyle,
  232. ),
  233. )),
  234. ),
  235. ],
  236. ),
  237. ): Container(
  238. child: widget.bottomFooterBuilder?.call(context),
  239. ),
  240. ),
  241. ],
  242. ),
  243. ),
  244. ),
  245. ),
  246. // 右上角 关闭按钮
  247. Visibility(
  248. visible: widget.showCloseIcon,
  249. child: Positioned(
  250. top: -2,
  251. right: 0,
  252. child: MyAssetImage(
  253. Assets.baseServiceDialogDeleteIcon,
  254. width: 25,
  255. height: 25.5,
  256. color: context.appColors.textPrimary,
  257. ).onTap((){
  258. onCancel();
  259. },padding: 10),
  260. ),
  261. )
  262. ],
  263. );
  264. }
  265. //取消弹框
  266. void onCancel() async {
  267. SmartDialog.dismiss();
  268. }
  269. }