import 'package:doctor_app_flutter/config/size_config.dart'; import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; import 'package:doctor_app_flutter/utils/utils.dart'; import 'package:doctor_app_flutter/widgets/shared/text_fields/text_field_error.dart'; import 'package:doctor_app_flutter/widgets/shared/text_fields/text_fields_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '../app_texts_widget.dart'; class AppTextFieldCustom extends StatefulWidget { final double height; final Function()? onClick; final String? hintText; final TextEditingController? controller; final bool isTextFieldHasSuffix; final bool hasBorder; final String? dropDownText; final IconButton? suffixIcon; final Widget? suffixWidget; final Color? dropDownColor; final bool enabled; final TextInputType? inputType; final int minLines; final int maxLines; final List? inputFormatters; final Function(String? value) onChanged; final Function() onFieldSubmitted; final VoidCallback? onEditingComplete; final String? validationError; final bool isPrscription; final bool isSecure; final bool focus; final bool isSearchTextField; AppTextFieldCustom({ this.height = 0, this.onClick, this.hintText, this.controller, this.hasBorder = true, this.isTextFieldHasSuffix = false, this.dropDownText, this.suffixIcon, this.suffixWidget, this.dropDownColor, this.enabled = true, this.inputType, this.minLines = 1, this.maxLines = 1, this.inputFormatters, required this.onChanged, this.validationError, this.isPrscription = false, this.isSecure = false, this.focus = false, this.isSearchTextField = false, required this.onFieldSubmitted, this.onEditingComplete }); @override _AppTextFieldCustomState createState() => _AppTextFieldCustomState(); } class _AppTextFieldCustomState extends State { final FocusNode _focusNode = FocusNode(); bool focus = false; bool view = false; @override void initState() { super.initState(); _focusNode.addListener(() { setState(() { focus = _focusNode.hasFocus; }); }); } @override void didUpdateWidget(AppTextFieldCustom oldWidget) { if (widget.focus) _focusNode.requestFocus(); super.didUpdateWidget(oldWidget); } @override void dispose() { // _focusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { ProjectViewModel projectViewModel = Provider.of(context); TextInputType localKeyboardType = widget.inputType ?? (widget.maxLines == 1 ? TextInputType.text : TextInputType.multiline); return Column( children: [ Container( height: widget.height != 0 && widget.maxLines == 1 ? widget.height + 8 : null, //MediaQuery.of(context).size.height * 0.098, decoration: widget.hasBorder ? TextFieldsUtils.containerBorderDecoration( Color(0Xffffffff), widget.validationError == null ? Color(0xFFEFEFEF) : Colors.red.shade700, ) : null, padding: EdgeInsets.only(top: 4.0, bottom: 0.0, left: 8.0, right: 8.0), child: InkWell( onTap: widget.onClick, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Container( padding: widget.dropDownText == null ? widget.isSearchTextField ? EdgeInsets.only(top: 10) : EdgeInsets.only(top: 0.5) : EdgeInsets.only(top: 0), // 8.0 child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ AppText( widget.hintText!, color: Color(0xFF2E303A), fontSize: widget.isPrscription == false ? 11.0 : 0, fontWeight: FontWeight.w600, letterSpacing: -0.44, fontFamily: 'Poppins', ), widget.dropDownText == null ? Container( height: widget.height != 0 && widget.maxLines == 1 ? widget.height - 22 : null, child: RawKeyboardListener( focusNode: FocusNode(), autofocus: false, onKey: (rawKeyEvent) { final isFormSkippedEnterEvent = rawKeyEvent is RawKeyDownEvent && rawKeyEvent.isKeyPressed( LogicalKeyboardKey.enter); final needToInsertNewLine = isFormSkippedEnterEvent && localKeyboardType == TextInputType.multiline; if (needToInsertNewLine) { TextEditingControllerHelper.insertText( widget.controller!, '\n'); } }, child: TextFormField( textInputAction: TextInputAction.done, onEditingComplete: (){ widget.onEditingComplete?.call(); }, textAlign: projectViewModel.isArabic ? TextAlign.right : TextAlign.left, focusNode: _focusNode, textAlignVertical: TextAlignVertical.top, decoration: TextFieldsUtils .textFieldSelectorDecoration( widget.hintText!, "", true), style: TextStyle( fontSize: SizeConfig.textMultiplier! * 1.7, fontFamily: 'Poppins', color: Color(0xFF575757), fontWeight: FontWeight.w400, letterSpacing: -0.56, ), controller: widget.controller, keyboardType: localKeyboardType, enabled: widget.enabled, minLines: widget.minLines, maxLines: widget.maxLines, inputFormatters: widget.inputFormatters != null ? widget.inputFormatters : [], onChanged: (value) { if (widget.onChanged != null) { widget.onChanged(value); } setState(() {}); }, onFieldSubmitted: widget.onFieldSubmitted(), obscureText: widget.isSecure), ), ) : AppText( Utils.convertToTitleCase(widget.dropDownText!), fontFamily: 'Poppins', color: Color(0xFF575757), fontSize: SizeConfig.textMultiplier! * 1.7, ), ], ), ), ), widget.isTextFieldHasSuffix ? widget.suffixIcon != null ? Container( margin: EdgeInsets.only( bottom: widget.isSearchTextField ? (widget.controller!.text.isEmpty || widget.controller == null) ? 10 : 25 : 0), child: widget.suffixIcon) : InkWell( child: Icon( Icons.keyboard_arrow_down, color: widget.dropDownColor != null ? widget.dropDownColor : Color(0xff2E303A), size: 12.0, ), ) : widget.suffixWidget != null ? widget.suffixWidget ?? SizedBox.shrink() : Container(), ], ), ), ), if (widget.validationError != null && widget.validationError!.isNotEmpty) TextFieldsError(error: widget.validationError!), ], ); } } class TextEditingControllerHelper { static insertText(TextEditingController controller, String textToInsert) { final selection = controller.selection; final cursorPosition = selection.base.offset; if (cursorPosition < 0) { controller.text += textToInsert; return; } final text = controller.text; final newText = text.replaceRange(selection.start, selection.end, textToInsert); controller.value = controller.value.copyWith( text: newText, selection: TextSelection.collapsed( offset: selection.baseOffset + textToInsert.length, ), ); } }