You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

244 lines
8.0KB

  1. import 'package:farm_tpf/themes/app_dimension.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:flutter_svg/svg.dart';
  5. import '../../../themes/app_colors.dart';
  6. import '../../../themes/styles_text.dart';
  7. import '../../../utils/app_images.dart';
  8. import '../../../utils/validators.dart';
  9. class TextFieldNormal extends StatefulWidget {
  10. final TextEditingController controller;
  11. final Function(String)? onFieldSubmitted;
  12. final Function(String)? onChanged;
  13. final FormFieldValidator<String>? validator;
  14. final String hint;
  15. final FocusNode? focusNode;
  16. final TextInputType? keyboardType;
  17. final TextInputAction? textInputAction;
  18. final List<TextInputFormatter>? inputFormatters;
  19. final bool? obscureText;
  20. final String? errorText;
  21. final Color? borderColor;
  22. final bool? isPasswordField;
  23. final Widget? prefixIcon;
  24. final String? prefixText;
  25. final int? maxLength;
  26. final bool? disabled;
  27. final TextCapitalization? textCapitalization;
  28. final String? suffixText;
  29. final HexColor? disableColor;
  30. final InputBorder? customBorder;
  31. final int? maxLines;
  32. final bool? autofocus;
  33. final EdgeInsetsGeometry? contentPadding;
  34. final Color? fillColor;
  35. final Color? hintColor;
  36. final TextStyle? inputStyle;
  37. final Widget? suffixIcon;
  38. final TextAlign textAlign;
  39. final VoidCallback? onTap;
  40. final bool readOnly;
  41. TextFieldNormal({
  42. required this.controller,
  43. required this.hint,
  44. this.validator,
  45. this.onFieldSubmitted,
  46. this.focusNode,
  47. this.keyboardType,
  48. this.textInputAction,
  49. this.inputFormatters,
  50. this.obscureText,
  51. this.errorText,
  52. this.onChanged,
  53. this.borderColor,
  54. this.isPasswordField,
  55. this.prefixIcon,
  56. this.maxLength,
  57. this.disabled,
  58. this.textCapitalization,
  59. this.suffixText,
  60. this.disableColor,
  61. this.prefixText,
  62. this.customBorder,
  63. this.maxLines,
  64. this.autofocus,
  65. this.contentPadding,
  66. this.fillColor,
  67. this.hintColor,
  68. this.inputStyle,
  69. this.suffixIcon,
  70. this.textAlign = TextAlign.start,
  71. this.onTap,
  72. this.readOnly = false,
  73. });
  74. @override
  75. _TextFieldNormalState createState() => _TextFieldNormalState();
  76. }
  77. class _TextFieldNormalState extends State<TextFieldNormal> {
  78. var isObscureText = false;
  79. late HexColor disableColor;
  80. final _errorMessage = ValueNotifier('');
  81. @override
  82. void initState() {
  83. super.initState();
  84. isObscureText = widget.isPasswordField ?? false;
  85. disableColor = widget.disableColor ?? AppColors.white;
  86. }
  87. @override
  88. Widget build(BuildContext context) {
  89. return Column(
  90. crossAxisAlignment: CrossAxisAlignment.start,
  91. children: [
  92. TextFormField(
  93. textAlign: widget.textAlign,
  94. keyboardType: widget.keyboardType ?? TextInputType.text,
  95. textInputAction: widget.textInputAction ?? TextInputAction.done,
  96. inputFormatters: widget.inputFormatters,
  97. obscureText: isObscureText,
  98. controller: widget.controller,
  99. validator: onValidator,
  100. readOnly: widget.readOnly,
  101. onTap: widget.onTap,
  102. onFieldSubmitted: widget.onFieldSubmitted,
  103. focusNode: widget.focusNode,
  104. autocorrect: false,
  105. autofocus: widget.autofocus ?? false,
  106. onChanged: widget.onChanged,
  107. maxLength: widget.maxLength,
  108. style: widget.inputStyle ?? StylesText.body6,
  109. maxLines: widget.maxLines ?? 1,
  110. autovalidateMode: AutovalidateMode.disabled,
  111. enabled: widget.disabled != true,
  112. textCapitalization: widget.textCapitalization ?? TextCapitalization.none,
  113. decoration: InputDecoration(
  114. contentPadding: widget.contentPadding ?? const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
  115. isDense: true,
  116. counterText: '',
  117. suffixText: widget.suffixText,
  118. prefixIconConstraints: const BoxConstraints(maxHeight: 20),
  119. suffixIconConstraints: const BoxConstraints(maxHeight: 20),
  120. prefixIcon: widget.prefixIcon,
  121. suffixIcon: widget.isPasswordField != null
  122. ? Padding(
  123. padding: const EdgeInsetsDirectional.only(end: 20.0),
  124. child: InkWell(
  125. onTap: () {
  126. setState(
  127. () {
  128. isObscureText = !isObscureText;
  129. },
  130. );
  131. },
  132. child: isObscureText
  133. ? SizedBox(
  134. width: 20.w,
  135. height: 20.h,
  136. child: SvgPicture.asset(
  137. AssetSVG.eye,
  138. ),
  139. )
  140. : SizedBox(
  141. width: 20.w,
  142. height: 20.h,
  143. child: SvgPicture.asset(
  144. AssetSVG.eyeOff,
  145. ),
  146. ),
  147. ),
  148. )
  149. : widget.suffixIcon,
  150. enabledBorder: widget.customBorder ??
  151. OutlineInputBorder(
  152. borderRadius: BorderRadius.circular(12),
  153. borderSide: BorderSide(
  154. color: widget.borderColor ?? AppColors.neutral4,
  155. width: 1,
  156. ),
  157. ),
  158. focusedBorder: widget.customBorder ??
  159. OutlineInputBorder(
  160. borderRadius: BorderRadius.circular(12),
  161. borderSide: BorderSide(
  162. color: widget.borderColor ?? AppColors.neutral4,
  163. width: 1,
  164. ),
  165. ),
  166. errorBorder: OutlineInputBorder(
  167. borderRadius: BorderRadius.circular(12),
  168. borderSide: BorderSide(
  169. color: widget.borderColor ?? AppColors.semantic6,
  170. width: 1,
  171. ),
  172. ),
  173. focusedErrorBorder: OutlineInputBorder(
  174. borderRadius: BorderRadius.circular(12),
  175. borderSide: BorderSide(
  176. color: widget.borderColor ?? AppColors.semantic6,
  177. width: 1,
  178. ),
  179. ),
  180. disabledBorder: OutlineInputBorder(
  181. borderRadius: BorderRadius.circular(12),
  182. borderSide: BorderSide(
  183. color: widget.borderColor ?? AppColors.neutral4,
  184. width: 1,
  185. ),
  186. ),
  187. hintText: widget.hint,
  188. hintStyle: StylesText.body6.copyWith(
  189. color: widget.hintColor ?? AppColors.neutral3,
  190. ),
  191. errorStyle: const TextStyle(fontSize: 0, height: 0),
  192. fillColor:
  193. (widget.disabled ?? false) ? (widget.disableColor ?? AppColors.background1.withOpacity(0.1)) : (widget.fillColor ?? Colors.white),
  194. filled: true,
  195. ),
  196. ),
  197. ValueListenableBuilder<String>(
  198. valueListenable: _errorMessage,
  199. builder: (context, message, _) {
  200. if (Validators.stringNotNullOrEmpty(message)) {
  201. return Padding(
  202. padding: const EdgeInsets.only(top: 0.0),
  203. child: Row(
  204. children: [
  205. SvgPicture.asset(AssetSVG.icWarning),
  206. const SizedBox(
  207. width: 4,
  208. ),
  209. Text(
  210. message,
  211. style: StylesText.caption3.copyWith(
  212. color: AppColors.semantic6,
  213. ),
  214. ),
  215. ],
  216. ),
  217. );
  218. } else {
  219. return const SizedBox.shrink();
  220. }
  221. },
  222. ),
  223. ],
  224. );
  225. }
  226. String? onValidator(String? value) {
  227. if (widget.validator != null) {
  228. _errorMessage.value = widget.validator!(value!) ?? '';
  229. return widget.validator!(value);
  230. } else {
  231. _errorMessage.value = '';
  232. return null;
  233. }
  234. }
  235. }