import 'package:flutter/widgets.dart'; class _Scope extends InheritedWidget { _Scope({ Key? key, this.formState, this.generation, required this.child, }) : super(key: key, child: child); final Widget child; final int? generation; final WFormState? formState; ///通过验证[generation]的变化进行刷新 @override bool updateShouldNotify(_Scope oldWidget) => generation != oldWidget.generation; } ///基于[Form]进行改造,实现双向绑定 /// ///[WFormState.values]可获取到表单全部数据 /// ///[WFormState.setValue]设置一个对应[field]的值 /// ///[WFormState.mergeValues]合并[values] class WForm extends StatefulWidget { WForm({ Key? key, this.child, this.autovalidateMode = AutovalidateMode.disabled, this.autoLostFocus = true, this.onWillPop, this.onChanged, this.initialValues, }) : super(key: key); static WFormState? of(BuildContext context) { final _Scope? scope = context.dependOnInheritedWidgetOfExactType<_Scope>(); return scope?.formState; } ///失去焦点 static void lostFocus(BuildContext context) => FocusScope.of(context).requestFocus( FocusNode(), ); final AutovalidateMode autovalidateMode; ///自动失去焦点 final bool autoLostFocus; final WillPopCallback? onWillPop; final VoidCallback? onChanged; final Widget? child; final Map? initialValues; @override WFormState createState() => WFormState(); } class WFormState extends State { final _formKey = GlobalKey(); int _generation = 0; Map? _values; Map? _initialValues; @override void initState() { ///深拷贝 _values = Map.from(widget.initialValues ?? {}); ///深拷贝 _initialValues = Map.from(widget.initialValues ?? {}); super.initState(); } void _initValue(String field, value) { _values![field] = value; } @override Widget build(BuildContext context) { Widget? current = widget.child; if (widget.autoLostFocus) { current = GestureDetector( behavior: HitTestBehavior.translucent, onTap: () => FocusScope.of(context).requestFocus(FocusNode()), child: current, ); } current = Form( key: _formKey, child: current!, autovalidateMode: widget.autovalidateMode, onWillPop: widget.onWillPop, onChanged: widget.onChanged, ); current = _Scope( formState: this, generation: _generation, child: current, ); return current; } Map? get values => _values; Map get initialValues => _initialValues ?? {}; ///保存,同[FormState.save] void save() => _formKey.currentState?.save(); ///初始化,同[FormState.reset] void reset() { _formKey.currentState?.reset(); _generation++; } ///验证表单,同[FormState.validate] void validate() => _formKey.currentState?.validate(); ///[WFormState.setValue]设置一个对应[field]的值 void setValue(String field, value) { if (_values![field] != value) { _values![field] = value; _generation++; setState(() {}); } } ///[WFormState.mergeValues]合并[values] void mergeValues(Map values) { final newValues = _values!..addAll(values); if (newValues != _values) { _values = newValues; _generation++; setState(() {}); } } } typedef WFormFieldBuilder = Widget Function(WFormFieldState fieldState); ///表单项构造 /// /// 与[FormField] 类似 class WFormField extends FormField { WFormField({ Key? key, required this.field, required WFormFieldBuilder builder, FormFieldSetter? onSaved, FormFieldValidator? validator, AutovalidateMode? autovalidateMode = AutovalidateMode.disabled, bool enabled = true, }) : assert(field.isNotEmpty, 'field不能为空'), super( key: key, onSaved: onSaved, validator: validator, autovalidateMode: autovalidateMode, enabled: enabled, builder: (fieldState) => builder((fieldState as WFormFieldState) as WFormFieldState), ); final String field; @override WFormFieldState createState() => WFormFieldState(); } class WFormFieldState extends FormFieldState { @override WFormField get widget => super.widget as WFormField; @override T? get value => WForm.of(context)?.values![widget.field]; T? get initialValue => WForm.of(context)?.initialValues[widget.field]; String? _errorText; String? get errorText => _errorText; bool get hasError => _errorText != null; @override void setValue(T? value, {rebuild = false}) { if (widget.field != '') { if (rebuild == true) { WForm.of(context)!.setValue(widget.field, value); } else { WForm.of(context)!._initValue(widget.field, value); } } super.setValue(value); } @override void didChange(T? value) { setValue(value); super.didChange(value); } @override bool validate() { if (widget.validator != null) _errorText = widget.validator!(value); return hasError; } @override void reset() { setValue(initialValue); super.reset(); } }