import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class AppTextField extends StatefulWidget { const AppTextField({ super.key, this.controller, this.initialValue, this.label, this.hint, this.prefixIcon, this.suffixIcon, this.keyboardType, this.textInputAction, this.obscureText = false, this.readOnly = false, this.maxLines = 1, this.maxLength, this.validator, this.inputFormatters, this.onChanged, this.onSubmitted, this.onFinished, this.finishLength, this.debounceDuration = const Duration(milliseconds: 500), }); final TextEditingController? controller; final String? initialValue; final String? label; final String? hint; final Widget? prefixIcon; final Widget? suffixIcon; final TextInputType? keyboardType; final TextInputAction? textInputAction; final bool obscureText; final bool readOnly; final int maxLines; final int? maxLength; final FormFieldValidator? validator; final List? inputFormatters; final ValueChanged? onChanged; final ValueChanged? onSubmitted; final ValueChanged? onFinished; final int? finishLength; final Duration debounceDuration; @override State createState() => _AppTextFieldState(); } class _AppTextFieldState extends State { late final TextEditingController _controller; Timer? _debounce; @override void initState() { super.initState(); _controller = widget.controller ?? TextEditingController(text: widget.initialValue ?? ''); _controller.addListener(_handleInput); } void _handleInput() { final text = _controller.text; if (widget.finishLength != null && text.length == widget.finishLength) { widget.onFinished?.call(text); return; } _debounce?.cancel(); _debounce = Timer(widget.debounceDuration, () { widget.onFinished?.call(text); }); } @override void dispose() { _debounce?.cancel(); _controller.removeListener(_handleInput); if (widget.controller == null) _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return TextFormField( controller: _controller, keyboardType: widget.keyboardType, textInputAction: widget.textInputAction ?? TextInputAction.done, obscureText: widget.obscureText, readOnly: widget.readOnly, maxLines: widget.maxLines, maxLength: widget.maxLength, validator: widget.validator, inputFormatters: widget.inputFormatters, onChanged: widget.onChanged, onFieldSubmitted: widget.onSubmitted, onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), decoration: InputDecoration( labelText: widget.label, hintText: widget.hint, prefixIcon: widget.prefixIcon, suffixIcon: widget.suffixIcon, border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), counterText: '', ), ); } }