在颤动中检查验证之前验证变为真
validation is becomes true before validation is checked in flutter
我对验证有疑问。我的小部件字段验证在检查之前变为真。当我刚打开此页面时,验证自动变为 true。
我想要在用户输入后进行验证。但是在用户从现场输入内容之前,这种验证正在成为现实。所以有人可以帮助我吗?您的帮助将不胜感激。
这是我试过的代码。
class BspSignupPage extends StatefulWidget {
static const String routeName = "/bspSignup";
@override
_BspSignupPageState createState() => _BspSignupPageState();
}
class _BspSignupPageState extends State<BspSignupPage>
with AfterLayoutMixin<BspSignupPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// final TextEditingController _bspPhone = TextEditingController();
final MaskedTextController _bspPhone =
new MaskedTextController(mask: '(000)-000-0000');
final TextEditingController _bspBusinessName = TextEditingController();
final TextEditingController _bspBusinessLegalAddress =
TextEditingController();
final TextEditingController _bspBusinessLicense = TextEditingController();
final TextEditingController _bspLicenseAuthority = TextEditingController();
final TextEditingController _bspEstYear = TextEditingController();
final TextEditingController _bspNumberOfEmployee = TextEditingController();
final TextEditingController _bspBusinessDetailsComment =
TextEditingController();
final TextEditingController _countryCodeController =
new TextEditingController();
BSPSignupRepository _bspSignupRepository = new BSPSignupRepository();
bool bspcheck = false;
BspSignupCommonModel model = BspSignupCommonModel();
int radioValue = -1;
String _alternatephone;
String _businessname;
bool addressenabled = false;
List<dynamic> _type = <dynamic>[];
Map<String, dynamic> _typeValue;
String _establishyear;
String _numberofemployee;
LocationResult _pickedLocation;
DateTime selectedDate = DateTime.now();
bool flexibletime = false;
DateTime date;
TimeOfDay time;
Map<String, dynamic> bspsignupdata = new Map<String, dynamic>();
@override
void initState() {
super.initState();
print(model);
_bspNumberOfEmployee.text = "1";
_bspSignupRepository.getBSTypes().then((businessTypeResponse) {
print('businessTypeResponse');
print(businessTypeResponse);
if (businessTypeResponse['error'] != null) {
} else {
setState(() {
_type = businessTypeResponse['data']['businessTypes'];
});
}
});
setState(() {
date = new DateTime.now().add(new Duration(hours: 1));
time = new TimeOfDay.fromDateTime(date);
});
}
@override
void afterFirstLayout(BuildContext context) {
model = ModalRoute.of(context).settings.arguments;
if (model == null) {
model = new BspSignupCommonModel();
} else {
print('model for edit');
_setExistingDetails(model);
}
}
void _setExistingDetails(bspModel) {
_bspBusinessName.text = bspModel.businessLegalName;
_bspPhone.text = model.businessPhoneNumber;
_bspEstYear.text = model.businessYear;
_bspNumberOfEmployee.text = model.numberofEmployees;
_bspBusinessLegalAddress.text = model.businessLegalAddress;
_typeValue = model.businessTypes;
}
Widget _buildlegalbusinessname() {
return new TudoTextWidget(
controller: _bspBusinessName,
textCapitalization: TextCapitalization.sentences,
prefixIcon: Icon(Icons.business),
labelText: AppConstantsValue.appConst['bspSignup']['legalbusinessname']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['legalbusinessname']
['translation'],
validator: (val) =>
Validators.validateRequired(val, "Business legal name"),
onSaved: (val) {
_businessname = val;
bspsignupdata['businessname'] = _businessname;
},
);
}
Widget _buildalternatephone() {
return Row(
children: <Widget>[
new Expanded(
child: new TudoTextWidget(
controller: _countryCodeController,
enabled: false,
prefixIcon: Icon(FontAwesomeIcons.globe),
labelText: "code",
hintText: "Country Code",
),
flex: 2,
),
new SizedBox(
width: 10.0,
),
new Expanded(
child: new TudoNumberWidget(
controller: _bspPhone,
validator: Validators().validateMobile,
labelText: AppConstantsValue.appConst['bspSignup']['alternatephone']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['alternatephone']
['translation'],
prefixIcon: Icon(Icons.phone),
onSaved: (val) {
_alternatephone = val;
bspsignupdata['alternatephone'] = _alternatephone;
},
),
flex: 5,
),
],
);
}
Widget _buildestablishedyear() {
return new TudoNumberWidget(
controller: _bspEstYear,
prefixIcon: Icon(FontAwesomeIcons.calendar),
labelText: AppConstantsValue.appConst['bspSignup']['establishedyear']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['establishedyear']
['translation'],
validator: Validators().validateestablishedyear,
maxLength: 4,
onSaved: (val) {
_establishyear = val.trim();
bspsignupdata['establishyear'] = _establishyear;
},
);
}
Widget _buildnumberofemployees() {
return new TudoNumberWidget(
controller: _bspNumberOfEmployee,
prefixIcon: Icon(Icons.control_point_duplicate),
labelText: AppConstantsValue.appConst['bspSignup']['numberofemployees']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['numberofemployees']
['translation'],
validator: Validators().validatenumberofemployee,
onSaved: (val) {
_numberofemployee = val.trim();
bspsignupdata['numberofemployes'] = _numberofemployee;
},
);
}
Widget _buildbusinesslegaladdress() {
return Row(
children: <Widget>[
new Expanded(
child: new TudoTextWidget(
prefixIcon: Icon(Icons.business),
labelText: AppConstantsValue.appConst['bspSignup']
['businesslegaladdress']['translation'],
hintText: AppConstantsValue.appConst['bspSignup']
['businesslegaladdress']['translation'],
controller: _bspBusinessLegalAddress,
enabled: addressenabled,
validator: (val) =>
Validators.validateRequired(val, "Business legal name"),
),
flex: 5,
),
new SizedBox(
width: 10.0,
),
new Expanded(
child: new FloatingActionButton(
backgroundColor: colorStyles['primary'],
child: Icon(
FontAwesomeIcons.globe,
color: Colors.white,
),
elevation: 0,
onPressed: () async {
LocationResult result = await LocationPicker.pickLocation(
context,
"AIzaSyDZZeGlIGUIPs4o8ahJE_yq6pJv3GhbKQ8",
);
print("result = $result");
setState(() {
_pickedLocation = result;
addressenabled = !addressenabled;
});
// setState(() => _pickedLocation = result);
_bspBusinessLegalAddress.text = _pickedLocation.address;
model.businessGeoLocation = new BusinessGeoLocation(
lat: _pickedLocation.latLng.latitude.toString(),
lng: _pickedLocation.latLng.longitude.toString(),
);
},
),
flex: 2,
),
],
);
}
Widget _buildbusinesstype() {
return FormBuilder(
autovalidate: true,
child: FormBuilderCustomField(
attribute: "Business type",
validators: [FormBuilderValidators.required()],
formField: FormField(
builder: (FormFieldState<dynamic> field) {
return InputDecorator(
decoration: InputDecoration(
prefixIcon: Icon(Icons.perm_identity),
labelText: _type == []
? 'Select Personal Identification type'
: 'Business type',
hintText: "Select Personal Identification type",
errorText: field.errorText,
),
isEmpty: _typeValue == [],
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
// isExpanded: true,
hint: Text("Select Personal Identification type"),
value: _typeValue,
isDense: true,
onChanged: (dynamic newValue) {
print('newValue');
print(newValue);
setState(() {
_typeValue = newValue;
field.didChange(newValue);
});
},
items: _type.map(
(dynamic value) {
return new DropdownMenuItem(
value: value,
child: new Text(value['name']),
);
},
).toList(),
),
),
);
},
)),
);
}
Widget _buildlegalbusinesscheck() {
return TudoConditionWidget(
text: AppConstantsValue.appConst['bspSignup']['legalbusinesscheck']
['translation'],
errortext: AppConstantsValue.appConst['bspSignup']['errortext']
['translation'],
);
}
Widget content(BuildContext context, BspSignupViewModel bspSignupVm) {
final appBar = AppBar(
title: Text("BSP Signup"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
NavigationHelper.navigatetoBack(context);
},
),
centerTitle: true,
);
final bottomNavigationBar = Container(
color: Colors.transparent,
height: 56,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
_formKey.currentState.reset();
_bspPhone.clear();
_bspBusinessName.clear();
_bspBusinessLicense.clear();
_bspLicenseAuthority.clear();
_bspEstYear.clear();
_bspNumberOfEmployee.clear();
_bspBusinessDetailsComment.clear();
_bspBusinessLegalAddress.clear();
},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
textColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
model.businessLegalName = _bspBusinessName.text;
model.businessPhoneNumber = _bspPhone.text;
model.businessYear = _bspEstYear.text;
model.numberofEmployees = _bspNumberOfEmployee.text;
model.businessType = _typeValue['id'];
model.businessLegalAddress = _bspBusinessLegalAddress.text;
model.businessTypes = _typeValue;
print('model');
print(model.licensed);
if (_typeValue['name'].toLowerCase() ==
"Licensed / Registered".toLowerCase()) {
model.isLicensed = true;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BspLicensedSignupPage(
bspSignupCommonModel: model,
),
),
);
} else {
model.isLicensed = false;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BspUnlicensedSignupPage(
bspSignupCommonModel: model,
),
),
);
}
}
},
),
],
),
);
return Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
body: Container(
height: double.infinity,
width: double.infinity,
child: Form(
autovalidate: true,
key: _formKey,
child: Stack(
children: <Widget>[
// Background(),
SingleChildScrollView(
padding: const EdgeInsets.all(30.0),
child: new Container(
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildlegalbusinessname(),
_buildalternatephone(),
_buildestablishedyear(),
_buildnumberofemployees(),
SizedBox(
height: 5,
),
_buildbusinesslegaladdress(),
_buildbusinesstype(),
_buildlegalbusinesscheck(),
],
),
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
return new StoreConnector<AppState, BspSignupViewModel>(
converter: (Store<AppState> store) => BspSignupViewModel.fromStore(store),
onInit: (Store<AppState> store) {
_countryCodeController.text =
store.state.auth.loginUser.user.country.isdCode;
},
builder: (BuildContext context, BspSignupViewModel bspSignupVm) =>
content(context, bspSignupVm),
);
}
}
您的小部件字段验证在检查之前变为真,因为您已将静态标志设置为“自动验证”以解决此问题,您必须为此管理标志变量
示例:-
bool _autoValidate = false;
Form(
key: _formKey,
autovalidate: _autoValidate,
child: Container(child:Text("")));
并在第一次验证表单时更改标志值
void _buttonClicked(BuildContext context) {
setState(() {
_autoValidate = true;
});
}
更新:-
autovalidate 已从 Flutter v1.19 中弃用
将 autovalidate 替换为 autovalidateMode。autovalidateMode 可以具有以下 3 个值之一:
autovalidateMode: AutovalidateMode.disabled: 不会发生自动验证。
autovalidateMode: AutovalidateMode.always: 用于自动验证 FormField,即使没有用户交互。
autovalidateMode: AutovalidateMode.onUserInteraction: 用于仅在每次用户交互后自动验证 FormField。
我对验证有疑问。我的小部件字段验证在检查之前变为真。当我刚打开此页面时,验证自动变为 true。
我想要在用户输入后进行验证。但是在用户从现场输入内容之前,这种验证正在成为现实。所以有人可以帮助我吗?您的帮助将不胜感激。
这是我试过的代码。
class BspSignupPage extends StatefulWidget {
static const String routeName = "/bspSignup";
@override
_BspSignupPageState createState() => _BspSignupPageState();
}
class _BspSignupPageState extends State<BspSignupPage>
with AfterLayoutMixin<BspSignupPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// final TextEditingController _bspPhone = TextEditingController();
final MaskedTextController _bspPhone =
new MaskedTextController(mask: '(000)-000-0000');
final TextEditingController _bspBusinessName = TextEditingController();
final TextEditingController _bspBusinessLegalAddress =
TextEditingController();
final TextEditingController _bspBusinessLicense = TextEditingController();
final TextEditingController _bspLicenseAuthority = TextEditingController();
final TextEditingController _bspEstYear = TextEditingController();
final TextEditingController _bspNumberOfEmployee = TextEditingController();
final TextEditingController _bspBusinessDetailsComment =
TextEditingController();
final TextEditingController _countryCodeController =
new TextEditingController();
BSPSignupRepository _bspSignupRepository = new BSPSignupRepository();
bool bspcheck = false;
BspSignupCommonModel model = BspSignupCommonModel();
int radioValue = -1;
String _alternatephone;
String _businessname;
bool addressenabled = false;
List<dynamic> _type = <dynamic>[];
Map<String, dynamic> _typeValue;
String _establishyear;
String _numberofemployee;
LocationResult _pickedLocation;
DateTime selectedDate = DateTime.now();
bool flexibletime = false;
DateTime date;
TimeOfDay time;
Map<String, dynamic> bspsignupdata = new Map<String, dynamic>();
@override
void initState() {
super.initState();
print(model);
_bspNumberOfEmployee.text = "1";
_bspSignupRepository.getBSTypes().then((businessTypeResponse) {
print('businessTypeResponse');
print(businessTypeResponse);
if (businessTypeResponse['error'] != null) {
} else {
setState(() {
_type = businessTypeResponse['data']['businessTypes'];
});
}
});
setState(() {
date = new DateTime.now().add(new Duration(hours: 1));
time = new TimeOfDay.fromDateTime(date);
});
}
@override
void afterFirstLayout(BuildContext context) {
model = ModalRoute.of(context).settings.arguments;
if (model == null) {
model = new BspSignupCommonModel();
} else {
print('model for edit');
_setExistingDetails(model);
}
}
void _setExistingDetails(bspModel) {
_bspBusinessName.text = bspModel.businessLegalName;
_bspPhone.text = model.businessPhoneNumber;
_bspEstYear.text = model.businessYear;
_bspNumberOfEmployee.text = model.numberofEmployees;
_bspBusinessLegalAddress.text = model.businessLegalAddress;
_typeValue = model.businessTypes;
}
Widget _buildlegalbusinessname() {
return new TudoTextWidget(
controller: _bspBusinessName,
textCapitalization: TextCapitalization.sentences,
prefixIcon: Icon(Icons.business),
labelText: AppConstantsValue.appConst['bspSignup']['legalbusinessname']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['legalbusinessname']
['translation'],
validator: (val) =>
Validators.validateRequired(val, "Business legal name"),
onSaved: (val) {
_businessname = val;
bspsignupdata['businessname'] = _businessname;
},
);
}
Widget _buildalternatephone() {
return Row(
children: <Widget>[
new Expanded(
child: new TudoTextWidget(
controller: _countryCodeController,
enabled: false,
prefixIcon: Icon(FontAwesomeIcons.globe),
labelText: "code",
hintText: "Country Code",
),
flex: 2,
),
new SizedBox(
width: 10.0,
),
new Expanded(
child: new TudoNumberWidget(
controller: _bspPhone,
validator: Validators().validateMobile,
labelText: AppConstantsValue.appConst['bspSignup']['alternatephone']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['alternatephone']
['translation'],
prefixIcon: Icon(Icons.phone),
onSaved: (val) {
_alternatephone = val;
bspsignupdata['alternatephone'] = _alternatephone;
},
),
flex: 5,
),
],
);
}
Widget _buildestablishedyear() {
return new TudoNumberWidget(
controller: _bspEstYear,
prefixIcon: Icon(FontAwesomeIcons.calendar),
labelText: AppConstantsValue.appConst['bspSignup']['establishedyear']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['establishedyear']
['translation'],
validator: Validators().validateestablishedyear,
maxLength: 4,
onSaved: (val) {
_establishyear = val.trim();
bspsignupdata['establishyear'] = _establishyear;
},
);
}
Widget _buildnumberofemployees() {
return new TudoNumberWidget(
controller: _bspNumberOfEmployee,
prefixIcon: Icon(Icons.control_point_duplicate),
labelText: AppConstantsValue.appConst['bspSignup']['numberofemployees']
['translation'],
hintText: AppConstantsValue.appConst['bspSignup']['numberofemployees']
['translation'],
validator: Validators().validatenumberofemployee,
onSaved: (val) {
_numberofemployee = val.trim();
bspsignupdata['numberofemployes'] = _numberofemployee;
},
);
}
Widget _buildbusinesslegaladdress() {
return Row(
children: <Widget>[
new Expanded(
child: new TudoTextWidget(
prefixIcon: Icon(Icons.business),
labelText: AppConstantsValue.appConst['bspSignup']
['businesslegaladdress']['translation'],
hintText: AppConstantsValue.appConst['bspSignup']
['businesslegaladdress']['translation'],
controller: _bspBusinessLegalAddress,
enabled: addressenabled,
validator: (val) =>
Validators.validateRequired(val, "Business legal name"),
),
flex: 5,
),
new SizedBox(
width: 10.0,
),
new Expanded(
child: new FloatingActionButton(
backgroundColor: colorStyles['primary'],
child: Icon(
FontAwesomeIcons.globe,
color: Colors.white,
),
elevation: 0,
onPressed: () async {
LocationResult result = await LocationPicker.pickLocation(
context,
"AIzaSyDZZeGlIGUIPs4o8ahJE_yq6pJv3GhbKQ8",
);
print("result = $result");
setState(() {
_pickedLocation = result;
addressenabled = !addressenabled;
});
// setState(() => _pickedLocation = result);
_bspBusinessLegalAddress.text = _pickedLocation.address;
model.businessGeoLocation = new BusinessGeoLocation(
lat: _pickedLocation.latLng.latitude.toString(),
lng: _pickedLocation.latLng.longitude.toString(),
);
},
),
flex: 2,
),
],
);
}
Widget _buildbusinesstype() {
return FormBuilder(
autovalidate: true,
child: FormBuilderCustomField(
attribute: "Business type",
validators: [FormBuilderValidators.required()],
formField: FormField(
builder: (FormFieldState<dynamic> field) {
return InputDecorator(
decoration: InputDecoration(
prefixIcon: Icon(Icons.perm_identity),
labelText: _type == []
? 'Select Personal Identification type'
: 'Business type',
hintText: "Select Personal Identification type",
errorText: field.errorText,
),
isEmpty: _typeValue == [],
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
// isExpanded: true,
hint: Text("Select Personal Identification type"),
value: _typeValue,
isDense: true,
onChanged: (dynamic newValue) {
print('newValue');
print(newValue);
setState(() {
_typeValue = newValue;
field.didChange(newValue);
});
},
items: _type.map(
(dynamic value) {
return new DropdownMenuItem(
value: value,
child: new Text(value['name']),
);
},
).toList(),
),
),
);
},
)),
);
}
Widget _buildlegalbusinesscheck() {
return TudoConditionWidget(
text: AppConstantsValue.appConst['bspSignup']['legalbusinesscheck']
['translation'],
errortext: AppConstantsValue.appConst['bspSignup']['errortext']
['translation'],
);
}
Widget content(BuildContext context, BspSignupViewModel bspSignupVm) {
final appBar = AppBar(
title: Text("BSP Signup"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
NavigationHelper.navigatetoBack(context);
},
),
centerTitle: true,
);
final bottomNavigationBar = Container(
color: Colors.transparent,
height: 56,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {
_formKey.currentState.reset();
_bspPhone.clear();
_bspBusinessName.clear();
_bspBusinessLicense.clear();
_bspLicenseAuthority.clear();
_bspEstYear.clear();
_bspNumberOfEmployee.clear();
_bspBusinessDetailsComment.clear();
_bspBusinessLegalAddress.clear();
},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
textColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
model.businessLegalName = _bspBusinessName.text;
model.businessPhoneNumber = _bspPhone.text;
model.businessYear = _bspEstYear.text;
model.numberofEmployees = _bspNumberOfEmployee.text;
model.businessType = _typeValue['id'];
model.businessLegalAddress = _bspBusinessLegalAddress.text;
model.businessTypes = _typeValue;
print('model');
print(model.licensed);
if (_typeValue['name'].toLowerCase() ==
"Licensed / Registered".toLowerCase()) {
model.isLicensed = true;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BspLicensedSignupPage(
bspSignupCommonModel: model,
),
),
);
} else {
model.isLicensed = false;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BspUnlicensedSignupPage(
bspSignupCommonModel: model,
),
),
);
}
}
},
),
],
),
);
return Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
body: Container(
height: double.infinity,
width: double.infinity,
child: Form(
autovalidate: true,
key: _formKey,
child: Stack(
children: <Widget>[
// Background(),
SingleChildScrollView(
padding: const EdgeInsets.all(30.0),
child: new Container(
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildlegalbusinessname(),
_buildalternatephone(),
_buildestablishedyear(),
_buildnumberofemployees(),
SizedBox(
height: 5,
),
_buildbusinesslegaladdress(),
_buildbusinesstype(),
_buildlegalbusinesscheck(),
],
),
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
return new StoreConnector<AppState, BspSignupViewModel>(
converter: (Store<AppState> store) => BspSignupViewModel.fromStore(store),
onInit: (Store<AppState> store) {
_countryCodeController.text =
store.state.auth.loginUser.user.country.isdCode;
},
builder: (BuildContext context, BspSignupViewModel bspSignupVm) =>
content(context, bspSignupVm),
);
}
}
您的小部件字段验证在检查之前变为真,因为您已将静态标志设置为“自动验证”以解决此问题,您必须为此管理标志变量
示例:-
bool _autoValidate = false;
Form(
key: _formKey,
autovalidate: _autoValidate,
child: Container(child:Text("")));
并在第一次验证表单时更改标志值
void _buttonClicked(BuildContext context) {
setState(() {
_autoValidate = true;
});
}
更新:-
autovalidate 已从 Flutter v1.19 中弃用
将 autovalidate 替换为 autovalidateMode。autovalidateMode 可以具有以下 3 个值之一:
autovalidateMode: AutovalidateMode.disabled: 不会发生自动验证。
autovalidateMode: AutovalidateMode.always: 用于自动验证 FormField,即使没有用户交互。
autovalidateMode: AutovalidateMode.onUserInteraction: 用于仅在每次用户交互后自动验证 FormField。