multiple_picker_field.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * @Author: XianKaiQun
  3. * @Date: 2020-08-25 14:59:08
  4. * @LastEditors : WuWei
  5. * @LastEditTime : 2023-05-10 14:49:22
  6. * @Description:
  7. */
  8. import 'package:flutter/material.dart';
  9. import 'package:flutter/services.dart';
  10. import 'package:wisdom_cli/wisdom_cli.dart';
  11. typedef WMultiplePickerFieldBuilder<T> = Widget Function(
  12. List<T>? value,
  13. Future<void> Function() trigger,
  14. );
  15. typedef WMultiplePickerFieldOnChanged<T> = void Function(List<T>? value);
  16. ///减少逻辑代码的单选组件
  17. class WMultiplePickerField<T extends WPickerEntity> extends StatefulWidget {
  18. WMultiplePickerField({
  19. Key? key,
  20. required this.getData,
  21. required this.builder,
  22. this.title,
  23. this.value,
  24. this.onChanged,
  25. }) : super(key: key);
  26. final WMultiplePickerFieldBuilder<T> builder;
  27. final Widget? title;
  28. final WSinglePickerGetData<T> getData;
  29. final List<T>? value;
  30. final WMultiplePickerFieldOnChanged<T>? onChanged;
  31. @override
  32. _WMultiplePickerFieldState<T> createState() =>
  33. _WMultiplePickerFieldState<T>();
  34. }
  35. class _WMultiplePickerFieldState<T extends WPickerEntity>
  36. extends State<WMultiplePickerField<T>> {
  37. List<T>? _value;
  38. List<T>? get value => _value;
  39. @override
  40. void initState() {
  41. super.initState();
  42. _value = List.of(widget.value ?? []);
  43. }
  44. ///触发单选弹出层
  45. Future<void> _trigger() async {
  46. final res = await WPickerUtil.multiple<T>(
  47. context,
  48. title: widget.title,
  49. getData: widget.getData,
  50. initialValue: _value,
  51. );
  52. if (res != null) {
  53. _onChanged(res);
  54. }
  55. }
  56. ///触发[widget.onChanged],
  57. ///刷新视图[widget.builder]
  58. void _onChanged(List<T> value) {
  59. if (_value == value) return;
  60. _value = value;
  61. setState(() {});
  62. if (widget.onChanged != null) {
  63. widget.onChanged!(value);
  64. }
  65. }
  66. @override
  67. Widget build(BuildContext context) {
  68. return widget.builder(value, () => _trigger());
  69. }
  70. }
  71. ///picker表单
  72. class WMultiplePickerFormField<T extends WPickerEntity>
  73. extends WFormField<List<T>> {
  74. WMultiplePickerFormField({
  75. Key? key,
  76. required WMultiplePickerFieldBuilder<T> builder,
  77. required WSinglePickerGetData<T> getData,
  78. required this.field,
  79. Widget? title,
  80. this.onChanged,
  81. FormFieldSetter<List<T>>? onSaved,
  82. FormFieldValidator<List<T>>? validator,
  83. AutovalidateMode? autovalidateMode,
  84. bool enabled = true,
  85. }) : super(
  86. key: key,
  87. field: field,
  88. onSaved: onSaved,
  89. validator: validator,
  90. autovalidateMode: autovalidateMode,
  91. enabled: enabled,
  92. builder: (WFormFieldState<List<T>> fieldState) {
  93. final _fieldState = fieldState as _WMultiplePickerFormFieldState<T>;
  94. return WMultiplePickerField(
  95. title: title,
  96. value: _fieldState.value,
  97. getData: getData,
  98. builder: builder,
  99. onChanged: (value) {
  100. _fieldState.didChange(value as List<T>?);
  101. },
  102. );
  103. },
  104. );
  105. ///直接使用[textField]进行builder
  106. ///[buildName] 构造要显示的名称
  107. WMultiplePickerFormField.textField({
  108. Key? key,
  109. required String Function(List<T>? value) buildName,
  110. required WSinglePickerGetData<T> getData,
  111. required this.field,
  112. Widget? title,
  113. T? value,
  114. this.onChanged,
  115. TextEditingController? controller,
  116. FormFieldSetter<List<T>>? onSaved,
  117. FormFieldValidator<List<T>>? validator,
  118. AutovalidateMode? autovalidateMode,
  119. bool enabled = true,
  120. FocusNode? focusNode,
  121. InputDecoration? decoration,
  122. TextInputType? keyboardType,
  123. TextCapitalization textCapitalization = TextCapitalization.none,
  124. TextInputAction? textInputAction,
  125. TextStyle? style,
  126. StrutStyle? strutStyle,
  127. TextDirection? textDirection,
  128. TextAlign textAlign = TextAlign.start,
  129. TextAlignVertical? textAlignVertical,
  130. bool autofocus = false,
  131. // bool readOnly = false,
  132. ToolbarOptions? toolbarOptions,
  133. bool? showCursor,
  134. String obscuringCharacter = '•',
  135. bool obscureText = false,
  136. bool autocorrect = true,
  137. SmartDashesType? smartDashesType,
  138. SmartQuotesType? smartQuotesType,
  139. bool enableSuggestions = true,
  140. MaxLengthEnforcement maxLengthEnforcement = MaxLengthEnforcement.enforced,
  141. int? maxLines = 1,
  142. int? minLines,
  143. bool expands = false,
  144. int? maxLength,
  145. // GestureTapCallback onTap,
  146. VoidCallback? onEditingComplete,
  147. ValueChanged<String>? onFieldSubmitted,
  148. List<TextInputFormatter>? inputFormatters,
  149. double cursorWidth = 2.0,
  150. Radius? cursorRadius,
  151. Color? cursorColor,
  152. Brightness? keyboardAppearance,
  153. EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
  154. bool enableInteractiveSelection = true,
  155. InputCounterWidgetBuilder? buildCounter,
  156. ScrollPhysics? scrollPhysics,
  157. Iterable<String>? autofillHints,
  158. }) : super(
  159. key: key,
  160. field: field,
  161. onSaved: onSaved,
  162. validator: validator,
  163. autovalidateMode: autovalidateMode,
  164. enabled: enabled,
  165. builder: (WFormFieldState<List<T>> fieldState) {
  166. final state = fieldState as _WMultiplePickerFormFieldState<T>;
  167. //主题
  168. InputDecoration _decoration = decoration ?? InputDecoration();
  169. _decoration = _decoration.applyDefaults(
  170. Theme.of(state.context).inputDecorationTheme,
  171. );
  172. _decoration = _decoration.copyWith(
  173. suffixIconConstraints:
  174. _decoration.suffixIconConstraints ?? const BoxConstraints(),
  175. suffixIcon: _decoration.suffixIcon ??
  176. Icon(
  177. Icons.chevron_right,
  178. color: Colors.black38,
  179. ),
  180. errorText: state.errorText,
  181. );
  182. final _controller = controller ?? TextEditingController();
  183. _controller.value = _controller.value.copyWith(
  184. text: buildName(state.value),
  185. );
  186. return WMultiplePickerField(
  187. title: title,
  188. value: state.value,
  189. getData: getData,
  190. onChanged: (value) => state.didChange(value as List<T>?),
  191. builder: (value, trigger) {
  192. return TextField(
  193. controller: _controller,
  194. focusNode: focusNode,
  195. decoration: _decoration,
  196. keyboardType: keyboardType,
  197. textInputAction: textInputAction,
  198. style: style,
  199. strutStyle: strutStyle,
  200. textAlign: textAlign,
  201. textAlignVertical: textAlignVertical,
  202. textDirection: textDirection,
  203. textCapitalization: textCapitalization,
  204. autofocus: autofocus,
  205. toolbarOptions: toolbarOptions,
  206. readOnly: true,
  207. showCursor: showCursor,
  208. obscuringCharacter: obscuringCharacter,
  209. obscureText: obscureText,
  210. autocorrect: autocorrect,
  211. smartDashesType: smartDashesType ??
  212. (obscureText
  213. ? SmartDashesType.disabled
  214. : SmartDashesType.enabled),
  215. smartQuotesType: smartQuotesType ??
  216. (obscureText
  217. ? SmartQuotesType.disabled
  218. : SmartQuotesType.enabled),
  219. enableSuggestions: enableSuggestions,
  220. maxLengthEnforcement: maxLengthEnforcement,
  221. maxLines: maxLines,
  222. minLines: minLines,
  223. expands: expands,
  224. maxLength: maxLength,
  225. // onChanged: onChangedHandler,
  226. onTap: () => trigger(),
  227. onEditingComplete: onEditingComplete,
  228. onSubmitted: onFieldSubmitted,
  229. inputFormatters: inputFormatters,
  230. enabled: enabled,
  231. cursorWidth: cursorWidth,
  232. cursorRadius: cursorRadius,
  233. cursorColor: cursorColor,
  234. scrollPadding: scrollPadding,
  235. scrollPhysics: scrollPhysics,
  236. keyboardAppearance: keyboardAppearance,
  237. enableInteractiveSelection: enableInteractiveSelection,
  238. buildCounter: buildCounter,
  239. autofillHints: autofillHints,
  240. );
  241. },
  242. );
  243. },
  244. );
  245. final String field;
  246. final WMultiplePickerFieldOnChanged<T>? onChanged;
  247. @override
  248. _WMultiplePickerFormFieldState<T> createState() =>
  249. _WMultiplePickerFormFieldState<T>();
  250. }
  251. class _WMultiplePickerFormFieldState<T extends WPickerEntity>
  252. extends WFormFieldState<List<T>> {
  253. @override
  254. WMultiplePickerFormField<T> get widget =>
  255. super.widget as WMultiplePickerFormField<T>;
  256. @override
  257. void didChange(List<T>? value) {
  258. super.didChange(value);
  259. if (widget.onChanged != null) {
  260. widget.onChanged!(value);
  261. }
  262. }
  263. }