my_text_field.dart 7.2 KB

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