具有空安全性的颤动表单验证器
flutter form validator with null safety
我在尝试在我的登录屏幕上制作表单验证器时遇到问题,当我磁带登录并且文本字段已经为空时它不起作用。如果您有任何帮助,这是我的代码,我想:
TextFormField 验证参数采用一个函数,如果字段内容有效,则 return 为空,如果内容无效,则为字符串。我的 flutter 项目中有 null 安全性,我的验证函数不能 return null。我如何编写一个启用空安全的有效验证函数?
登录代码屏幕:
import 'package:flutter/material.dart';
import 'package:flutter_udemy/shared/components/components.dart';
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
var emailController = TextEditingController();
var passwordController = TextEditingController();
var formKey = GlobalKey<FormState>();
bool isPassword = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
defaultFormField(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String value) {
if (value.isEmpty) {
return 'email must not be empty';
}
return null;
},
),
SizedBox(
height: 15.0,
),
defaultFormField(
controller: passwordController,
label: 'Password',
prefix: Icons.lock,
suffix:
isPassword ? Icons.visibility : Icons.visibility_off,
isPassword: isPassword,
suffixPressed: () {
setState(() {
isPassword = !isPassword;
});
},
type: TextInputType.visiblePassword,
validate: (String value) {
if (value.isEmpty) {
return 'password is too short';
}
return null;
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'login',
function: () {
if (formKey.currentState!.validate()) {
print(emailController.text);
print(passwordController.text);
}
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'ReGIster',
function: () {
print(emailController.text);
print(passwordController.text);
},
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
),
TextButton(
onPressed: () {},
child: Text(
'Register Now',
),
),
],
),
],
),
),
),
),
),
);
}
}
我得到按钮小部件和文本字段小部件的组件代码屏幕:
import 'package:flutter/material.dart';
Widget defaultButton({
double width = double.infinity,
Color background = Colors.blue,
bool isUpperCase = true,
double radius = 10.0,
required Function function,
required String text,
}) =>
Container(
width: width,
height: 50.0,
child: MaterialButton(
onPressed: () {
function();
},
child: Text(
isUpperCase ? text.toUpperCase() : text,
style: TextStyle(
color: Colors.white,
),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
radius,
),
color: background,
),
);
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit,
Function? onChange,
bool isPassword = false,
required Function validate,
required String label,
required IconData prefix,
IconData? suffix,
Function? suffixPressed,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
obscureText: isPassword,
onFieldSubmitted: (s) {
onSubmit!(s);
},
onChanged: (s) {
onChange!(s);
},
validator: (s) {
validate(s);
},
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(
prefix,
),
suffixIcon: suffix != null
? IconButton(
onPressed: () {
suffixPressed!();
},
icon: Icon(
suffix,
),
)
: null,
border: OutlineInputBorder(),
),
);
此代码有效
为零安全所做的主要更改
需要字符串吗?函数(字符串?)?验证
validate: (String? value) {
if (value!.isEmpty)
{
return 'email must not be empty';
}
return null;
},
完整代码如下
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
var emailController = TextEditingController();
var passwordController = TextEditingController();
final formKey = GlobalKey<FormState>();
bool isPassword = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
defaultFormField(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String? value) {
if (value!.isEmpty) {
return 'email must not be empty';
}
return null;
},
),
SizedBox(
height: 15.0,
),
defaultFormField(
controller: passwordController,
label: 'Password',
prefix: Icons.lock,
suffix:
isPassword ? Icons.visibility : Icons.visibility_off,
isPassword: isPassword,
suffixPressed: () {
setState(() {
isPassword = !isPassword;
});
},
type: TextInputType.visiblePassword,
validate: (String? value) {
if (value!.isEmpty) {
return 'password is too short';
}
return null;
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'login',
function: () {
if (formKey.currentState!.validate()) {
print(emailController.text);
print(passwordController.text);
}
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'ReGIster',
function: () {
print(emailController.text);
print(passwordController.text);
},
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
),
TextButton(
onPressed: () {},
child: Text(
'Register Now',
),
),
],
),
],
),
),
),
),
),
);
}
Widget defaultButton({
double width = double.infinity,
Color background = Colors.blue,
bool isUpperCase = true,
double radius = 10.0,
required Function function,
required String text,
}) =>
Container(
width: width,
height: 50.0,
child: MaterialButton(
onPressed: () {
function();
},
child: Text(
isUpperCase ? text.toUpperCase() : text,
style: TextStyle(
color: Colors.white,
),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
radius,
),
color: background,
),
);
}
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit,
Function? onChange,
bool isPassword = false,
required String? Function(String?)? validate,
required String label,
required IconData prefix,
IconData? suffix,
Function? suffixPressed,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
obscureText: isPassword,
onFieldSubmitted: (s) {
onSubmit!(s);
},
onChanged: (s) {
onChange!(s);
},
validator: validate,
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(
prefix,
),
suffixIcon: suffix != null
? IconButton(
onPressed: () {
suffixPressed!();
},
icon: Icon(
suffix,
),
)
: null,
border: OutlineInputBorder(),
),
);
你可以试试这个
validate: (String? value) {
if (value == null || value.trim().isEmpty) {
return 'Please provide a value.';
}
return null;
}
我在尝试在我的登录屏幕上制作表单验证器时遇到问题,当我磁带登录并且文本字段已经为空时它不起作用。如果您有任何帮助,这是我的代码,我想: TextFormField 验证参数采用一个函数,如果字段内容有效,则 return 为空,如果内容无效,则为字符串。我的 flutter 项目中有 null 安全性,我的验证函数不能 return null。我如何编写一个启用空安全的有效验证函数?
登录代码屏幕:
import 'package:flutter/material.dart';
import 'package:flutter_udemy/shared/components/components.dart';
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
var emailController = TextEditingController();
var passwordController = TextEditingController();
var formKey = GlobalKey<FormState>();
bool isPassword = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
defaultFormField(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String value) {
if (value.isEmpty) {
return 'email must not be empty';
}
return null;
},
),
SizedBox(
height: 15.0,
),
defaultFormField(
controller: passwordController,
label: 'Password',
prefix: Icons.lock,
suffix:
isPassword ? Icons.visibility : Icons.visibility_off,
isPassword: isPassword,
suffixPressed: () {
setState(() {
isPassword = !isPassword;
});
},
type: TextInputType.visiblePassword,
validate: (String value) {
if (value.isEmpty) {
return 'password is too short';
}
return null;
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'login',
function: () {
if (formKey.currentState!.validate()) {
print(emailController.text);
print(passwordController.text);
}
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'ReGIster',
function: () {
print(emailController.text);
print(passwordController.text);
},
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
),
TextButton(
onPressed: () {},
child: Text(
'Register Now',
),
),
],
),
],
),
),
),
),
),
);
}
}
我得到按钮小部件和文本字段小部件的组件代码屏幕:
import 'package:flutter/material.dart';
Widget defaultButton({
double width = double.infinity,
Color background = Colors.blue,
bool isUpperCase = true,
double radius = 10.0,
required Function function,
required String text,
}) =>
Container(
width: width,
height: 50.0,
child: MaterialButton(
onPressed: () {
function();
},
child: Text(
isUpperCase ? text.toUpperCase() : text,
style: TextStyle(
color: Colors.white,
),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
radius,
),
color: background,
),
);
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit,
Function? onChange,
bool isPassword = false,
required Function validate,
required String label,
required IconData prefix,
IconData? suffix,
Function? suffixPressed,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
obscureText: isPassword,
onFieldSubmitted: (s) {
onSubmit!(s);
},
onChanged: (s) {
onChange!(s);
},
validator: (s) {
validate(s);
},
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(
prefix,
),
suffixIcon: suffix != null
? IconButton(
onPressed: () {
suffixPressed!();
},
icon: Icon(
suffix,
),
)
: null,
border: OutlineInputBorder(),
),
);
此代码有效
为零安全所做的主要更改
需要字符串吗?函数(字符串?)?验证
validate: (String? value) {
if (value!.isEmpty)
{
return 'email must not be empty';
}
return null;
},
完整代码如下
class LoginScreen extends StatefulWidget {
LoginScreen({Key? key}) : super(key: key);
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
var emailController = TextEditingController();
var passwordController = TextEditingController();
final formKey = GlobalKey<FormState>();
bool isPassword = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Login',
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 40.0,
),
defaultFormField(
controller: emailController,
label: 'Email',
prefix: Icons.email,
type: TextInputType.emailAddress,
validate: (String? value) {
if (value!.isEmpty) {
return 'email must not be empty';
}
return null;
},
),
SizedBox(
height: 15.0,
),
defaultFormField(
controller: passwordController,
label: 'Password',
prefix: Icons.lock,
suffix:
isPassword ? Icons.visibility : Icons.visibility_off,
isPassword: isPassword,
suffixPressed: () {
setState(() {
isPassword = !isPassword;
});
},
type: TextInputType.visiblePassword,
validate: (String? value) {
if (value!.isEmpty) {
return 'password is too short';
}
return null;
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'login',
function: () {
if (formKey.currentState!.validate()) {
print(emailController.text);
print(passwordController.text);
}
},
),
SizedBox(
height: 20.0,
),
defaultButton(
text: 'ReGIster',
function: () {
print(emailController.text);
print(passwordController.text);
},
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Don\'t have an account?',
),
TextButton(
onPressed: () {},
child: Text(
'Register Now',
),
),
],
),
],
),
),
),
),
),
);
}
Widget defaultButton({
double width = double.infinity,
Color background = Colors.blue,
bool isUpperCase = true,
double radius = 10.0,
required Function function,
required String text,
}) =>
Container(
width: width,
height: 50.0,
child: MaterialButton(
onPressed: () {
function();
},
child: Text(
isUpperCase ? text.toUpperCase() : text,
style: TextStyle(
color: Colors.white,
),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
radius,
),
color: background,
),
);
}
Widget defaultFormField({
required TextEditingController controller,
required TextInputType type,
Function? onSubmit,
Function? onChange,
bool isPassword = false,
required String? Function(String?)? validate,
required String label,
required IconData prefix,
IconData? suffix,
Function? suffixPressed,
}) =>
TextFormField(
controller: controller,
keyboardType: type,
obscureText: isPassword,
onFieldSubmitted: (s) {
onSubmit!(s);
},
onChanged: (s) {
onChange!(s);
},
validator: validate,
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(
prefix,
),
suffixIcon: suffix != null
? IconButton(
onPressed: () {
suffixPressed!();
},
icon: Icon(
suffix,
),
)
: null,
border: OutlineInputBorder(),
),
);
你可以试试这个
validate: (String? value) {
if (value == null || value.trim().isEmpty) {
return 'Please provide a value.';
}
return null;
}