如何将用户的TextFormField输入传递给flutter中不同类的按钮
Posted
技术标签:
【中文标题】如何将用户的TextFormField输入传递给flutter中不同类的按钮【英文标题】:How to pass user's TextFormField input to a button in a different class in flutter 【发布时间】:2021-05-06 13:03:06 【问题描述】:我正在创建一个颤振应用程序。为了代码的可重用性,我需要区分电子邮件和密码表单以及登录按钮,我不确定如何正确地将输入从 textformfield 传递到按钮,以便在单击时验证表单。这是我的代码。请注意,我是 Flutter 的初学者。
//这是我的 EmailTextForm 类:
class EmailTextForm extends StatelessWidget
String email;
EmailTextForm(Key key, this.email) : super(key: key);
Widget build(BuildContext context)
return Container(
width: 370.0,
height: 54.0,
child: TextFormField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
//DEFAULT STATE OF THE BORDER(FOCUSED BORDER DOWN BELOW TO HAVE MORE CONTROL OF THE FORM)
borderSide: BorderSide(
width: 1.0, color: Color.fromRGBO(16, 25, 53, 0.1)),
borderRadius: BorderRadius.circular(12.0)),
focusedBorder: OutlineInputBorder(
//ON FOCUSED BORDER TO NOT CHANGE STATE WHILE BEING PRESSED ON
borderSide: BorderSide(
width: 1.0, color: Color.fromRGBO(16, 25, 53, 0.1)),
borderRadius: BorderRadius.circular(12.0),
),
prefixIcon: Icon(Icons.mail, color: Color(0xFF9FA3AE)),
hintText: 'El.Paštas',
hintStyle: TextStyle(
fontFamily: 'Sora',
fontSize: 16.0,
color: Color(0xFF9FA3AE),
),
),
validator: (input) =>
!input.contains('@') ? 'Please enter a valid email' : null,
onSaved: (input) => email = input,
));
//这是按钮类。
import 'package:flutter/material.dart';
import 'dart:math' as math;
class LoginButton extends StatelessWidget
final _formKey = GlobalKey<FormState>();
String email;
String password;
_submit()
if (_formKey.currentState.validate())
_formKey.currentState.save();
print('validated');
//logging in the user
@override
Widget build(BuildContext context)
//Container to manipulate button design
return Container(
width: 370.0,
height: 54.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular((12.0)),
gradient: LinearGradient(
//change gradient, wrong value, maybe something in AdobeXD.
colors: <Color>[Color(0xFF00BAFF), Color(0xFF448CFA)],
stops: [0.0, 1.0],
begin: Alignment(-1.0, 0.0),
end: Alignment(1.0, 0.0),
transform: GradientRotation(math.pi / 2),
),
boxShadow: [
BoxShadow(
color: Color.fromRGBO(48, 183, 241, 1.0),
offset: Offset(0.0, 4.0),
blurRadius: 12.0,
),
],
),
//@@@@ WHEN BUTTON IS PRESSED @@@@
child: ElevatedButton(
onPressed: _submit,
child: Text(
'Prisijungti',
),
style: ElevatedButton.styleFrom(
//COLOR OF THE TEXT INSIDE THE BUTTON
onPrimary: Color(0xFFFFFFFF),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
primary: Colors.transparent,
textStyle: TextStyle(
//Text inside button style
fontSize: 16.0,
fontWeight: FontWeight.w600,
fontFamily: 'Sora',
)),
));
【问题讨论】:
是否需要将按钮的文本设置为从TextFormField接收到的值或输入文本? 【参考方案1】:访问字段数据
底部的代码示例显示了访问电子邮件字段值的两种不同方法:
FormFieldState
TextEditingController
这两种方法不依赖于 Form
包装您的字段(尽管这样做通常很方便,为您提供了更多处理表单数据和显示验证错误的选项。)
为什么要使用Form
?
Form
小部件包装字段对于将多个字段作为一个组一起处理/操作非常有用,例如表单重置、验证和提交。
我们通过GlobalKey<FormState>
访问这些Form
函数,我们在声明它时将其提供给Form
。
child: Form(
key: formKey, // declared above as a field in our State object
例如,TextFormField
有一个 validator:
参数(接受一个函数)。如果我们的字段在 Form
内,我们可以要求 Form
调用所有验证器函数来“验证”我们的表单:
formKey.currentState.validate();
validator:
将显示您返回给它的任何非空字符串:
代码示例
import 'package:flutter/material.dart';
class FormValuesPage extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text('Form Values'),
),
body: FormValuesExample(),
);
class FormValuesExample extends StatefulWidget
@override
_FormValuesExampleState createState() => _FormValuesExampleState();
class _FormValuesExampleState extends State<FormValuesExample>
GlobalKey<FormState> formKey = GlobalKey<FormState>();
GlobalKey<FormFieldState> emailFieldKey = GlobalKey();
TextEditingController emailController = TextEditingController();
@override
void dispose()
emailController.dispose();
super.dispose();
@override
Widget build(BuildContext context)
return Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Form(
key: formKey, // declared above as a field in our State object
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextFormField(
key: emailFieldKey,
controller: emailController,
decoration: InputDecoration(
labelText: 'Email'
),
validator: (val) => validateEmail(val),
),
LoginButton(formKey: formKey, fieldKey: emailFieldKey, controller: emailController,)
],
),
),
);
String validateEmail(String email)
if (email == null || email.isEmpty)
return 'Email cannot be empty';
return null;
class LoginButton extends StatelessWidget
final GlobalKey<FormState> formKey;
final GlobalKey<FormFieldState> fieldKey;
final TextEditingController controller;
LoginButton(this.formKey, this.fieldKey, this.controller);
@override
Widget build(BuildContext context)
return ElevatedButton(
onPressed: ()
formKey.currentState.validate();
print('from FormFieldState $fieldKey.currentState.value');
print('from controller: $controller.text');
,
child: Text('Submit'));
【讨论】:
【参考方案2】:您需要将它们包装在一个 Form 小部件中并传递密钥,例如:
Form(
key: _keyForm
child: Column(
children: <Widget>[
EmailTextFieldForm(),
PasswordTextFieldForm(),
FormButton(),
],
)
)
【讨论】:
【参考方案3】:您需要将所有 TextFormFields 包装在一个表单中才能像这样得到它
Column(
children: [
TextFormField(),
....
TextFormField(),
])
TextFormFields 可以被包装或移动到另一个小部件,只要它是窗体的子级。
如果一切都在一个小部件中
Form(
child:
Column(
children: [
TextFormField(),
....
TextFormField(),
Button(
onTap: () ,
),
])
您需要将按钮包装在 Builder 中,以便树中当前元素的上下文可用
Builder(
builder: (context) => Button(
onTap: () ,
),
),
然后,您可以使用Form.of(context).validate()
。该条目将在树中找到第一个表单并验证所有文本字段。
这样你就应该这样出去
Builder(
builder: (context) => Button(
onTap: ()
Form.of(context).validate()
,
),
)
如果按钮放置在单独的小部件中,则无需将其包装在 Builder 中,您可以简单地调用验证,因为您可以使用表单下方的上下文
Button(
onTap: ()
Form.of(context).validate()
,
),
另外,您可以创建 GlobalKey
并使用密钥进行验证。您可以传递密钥,例如,通过构造函数(如果需要)
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey
child: Column(
children: [
TextFormField(),
....
Button(
onTap: ()
_formKey.currentState!.validate ()
)
],
),
)
【讨论】:
以上是关于如何将用户的TextFormField输入传递给flutter中不同类的按钮的主要内容,如果未能解决你的问题,请参考以下文章
[译]TextField/TextFormField 如何显示/隐藏密码