my_text_field.dart 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import 'dart:async';
  2. import 'dart:core';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. import 'package:cs_resources/constants/color_constants.dart';
  6. import 'ext/ex_widget.dart';
  7. import 'utils/dark_theme_util.dart';
  8. // ignore: slash_for_doc_comments
  9. /**
  10. 输入框的封装
  11. */
  12. class MyTextField extends StatelessWidget {
  13. String formKey;
  14. String value;
  15. bool? enabled;
  16. TextInputType inputType;
  17. FocusNode? focusNode;
  18. String? labelText;
  19. TextStyle? labelStyle;
  20. String? errorText;
  21. double cursorWidth;
  22. Color? cursorColor = ColorConstants.appBlue;
  23. String? hintText;
  24. TextStyle? hintStyle;
  25. TextStyle? style;
  26. final String? subHintText; //提示附文本
  27. final TextStyle? subHintStyle;
  28. bool? autofocus;
  29. int? maxLines = 1;
  30. InputBorder? border;
  31. BoxBorder? boxBorder;
  32. bool? showLeftIcon;
  33. Widget? leftWidget;
  34. bool? showRightIcon;
  35. Widget? rightWidget;
  36. bool? showDivider;
  37. Color? dividerColor;
  38. bool obscureText;
  39. double height;
  40. Color? fillBackgroundColor;
  41. double? fillCornerRadius;
  42. EdgeInsetsGeometry padding;
  43. EdgeInsetsGeometry margin;
  44. InputDecoration? decoration;
  45. TextEditingController? controller;
  46. TextInputAction textInputAction = TextInputAction.done;
  47. List<TextInputFormatter>? inputFormatters;
  48. Function? onChanged;
  49. Function? onSubmit;
  50. final ClickType changeActionType; //默认没有点击类型
  51. final int changeActionMilliseconds; //点击类型的时间戳(毫秒)
  52. final ClickType submitActionType; //默认没有点击类型
  53. final int submitActionMilliseconds; //点击类型的时间戳(毫秒)
  54. MyTextField(
  55. this.formKey,
  56. this.value, {
  57. Key? key,
  58. this.enabled = true, //是否可用
  59. this.inputType = TextInputType.text, //输入类型
  60. this.focusNode, //焦点
  61. this.labelText,
  62. this.labelStyle,
  63. this.errorText, //错误的文本
  64. this.cursorWidth = 2.0, // 光标宽度
  65. this.cursorColor, // 光标颜色
  66. this.hintText, //提示文本
  67. this.hintStyle, //提示文本样式
  68. this.subHintText, // 新的子提示文本
  69. this.subHintStyle, // 新的子提示文本样式
  70. this.style, //默认的文本样式
  71. this.autofocus = false, // 自动聚焦
  72. this.maxLines = 1, //最多行数,高度与行数同步
  73. this.border = InputBorder.none, //TextFiled的边框
  74. this.boxBorder, // 外层Container的边框
  75. this.showLeftIcon = false, //是否展示左侧的布局
  76. this.leftWidget, //左侧的布局
  77. this.showRightIcon = false, //是否展示右侧的布局
  78. this.rightWidget, //右侧的布局
  79. this.showDivider = true, // 是否显示下分割线
  80. this.dividerColor = const Color.fromARGB(255, 212, 212, 212), // 下分割线颜色
  81. this.obscureText = false, //是否隐藏文本,即显示密码类型
  82. this.height = 50.0,
  83. this.fillBackgroundColor, //整体的背景颜色
  84. this.fillCornerRadius = 5.0, //整体的背景颜色圆角
  85. this.padding = EdgeInsets.zero, //整体布局的Padding
  86. this.margin = EdgeInsets.zero, //整体布局的Margin
  87. this.decoration, //自定义装饰
  88. this.controller, //控制器
  89. this.inputFormatters, //输入格式控制
  90. this.textInputAction = TextInputAction.done, //默认的行为是Done(完成)
  91. this.onChanged, //输入改变回调
  92. this.onSubmit, //完成行为的回调(默认行为是Done完成)
  93. this.changeActionType = ClickType.none, //默认没有点击类型
  94. this.changeActionMilliseconds = 500, //回调类型的时间戳(毫秒)
  95. this.submitActionType = ClickType.none, //默认没有点击类型
  96. this.submitActionMilliseconds = 500, //回调类型的时间戳(毫秒)
  97. }) : super(key: key);
  98. @override
  99. Widget build(BuildContext context) {
  100. //抽取的改变的回调
  101. changeAction(value) {
  102. onChanged?.call(formKey, value);
  103. }
  104. //抽取的提交的回调
  105. submitAction(value) {
  106. onSubmit?.call(formKey, value);
  107. }
  108. return Container(
  109. margin: margin,
  110. decoration: BoxDecoration(
  111. color: fillBackgroundColor ?? Colors.transparent,
  112. borderRadius: BorderRadius.all(Radius.circular(fillCornerRadius ?? 0)),
  113. border: boxBorder,
  114. ),
  115. padding: padding,
  116. child: ConstrainedBox(
  117. constraints: BoxConstraints(minHeight: height),
  118. child: Column(
  119. mainAxisAlignment: maxLines == null ? MainAxisAlignment.start : MainAxisAlignment.center,
  120. children: [
  121. TextField(
  122. enabled: enabled,
  123. style: style,
  124. maxLines: maxLines,
  125. keyboardType: inputType,
  126. focusNode: focusNode,
  127. obscureText: obscureText,
  128. cursorWidth: cursorWidth,
  129. cursorColor: DarkThemeUtil.multiColors(context, cursorColor, darkColor: Colors.white),
  130. autofocus: autofocus!,
  131. controller: controller,
  132. inputFormatters: inputFormatters,
  133. decoration: decoration ??
  134. InputDecoration(
  135. hintText: hintText,
  136. hintStyle: hintStyle,
  137. icon: showLeftIcon == true ? leftWidget : null,
  138. border: border,
  139. suffixIcon: showRightIcon == true ? rightWidget : null,
  140. labelText: labelText,
  141. errorText: errorText,
  142. errorStyle: const TextStyle(color: Colors.redAccent, fontSize: 11.5, height: 0.5),
  143. errorBorder: const OutlineInputBorder(
  144. borderSide: BorderSide(color: Colors.redAccent),
  145. ),
  146. ),
  147. onChanged: changeActionType == ClickType.debounce
  148. ? debounce(changeAction, changeActionMilliseconds)
  149. : changeActionType == ClickType.throttle
  150. ? throttle(changeAction, changeActionMilliseconds)
  151. : changeAction,
  152. onSubmitted: submitActionType == ClickType.debounce
  153. ? debounce(submitAction, submitActionMilliseconds)
  154. : submitActionType == ClickType.throttle
  155. ? throttle(submitAction, submitActionMilliseconds)
  156. : submitAction,
  157. textInputAction: textInputAction,
  158. ),
  159. showDivider == true
  160. ? Divider(
  161. height: 0.3,
  162. color: dividerColor!,
  163. ).marginOnly(top: errorText == null ? 0 : 10)
  164. : const SizedBox.shrink(),
  165. ],
  166. ),
  167. ),
  168. );
  169. }
  170. //带参数的函数防抖,由于参数不固定就没有用过扩展,直接用方法包裹
  171. void Function(String value) debounce(void Function(String value) callback, [int milliseconds = 500]) {
  172. Timer? _debounceTimer;
  173. return (value) {
  174. if (_debounceTimer?.isActive ?? false) _debounceTimer?.cancel();
  175. _debounceTimer = Timer(Duration(milliseconds: milliseconds), () {
  176. callback(value);
  177. });
  178. };
  179. }
  180. //带参数的函数节流,由于参数不固定就没有用过扩展,直接用方法包裹
  181. void Function(String value) throttle(void Function(String value) callback, [int milliseconds = 500]) {
  182. bool _isAllowed = true;
  183. Timer? _throttleTimer;
  184. return (value) {
  185. if (!_isAllowed) return;
  186. _isAllowed = false;
  187. callback(value);
  188. _throttleTimer?.cancel();
  189. _throttleTimer = Timer(Duration(milliseconds: milliseconds), () {
  190. _isAllowed = true;
  191. });
  192. };
  193. }
  194. }