dialog_content_wrap.dart 13 KB

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