my_text_field.dart 7.3 KB

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