如何在不存在于同一文件中的两个小部件之间传递文本值



我有以下小部件,每个小部件都存在于自己的文件中。

(每个文件中都有很多内容。我对其进行了精简,以使其最小化,只查看此查询所需的内容(。

我希望在一个小部件中捕获传递到TextFormField的值,并在另一个小组件中打印出这些值。

没有视觉状态更改,因此尝试不通过Provider存储这些值,我觉得这对这个用例来说是愚蠢的。

因此,问题是如何将在TextEditingController中为每个小部件的实例捕获的值向下传递,并将其传递给另一个小部件?

重申一下,以下3个类存在于它们自己的Dart文件中。

我最初坚持使用所有3个无状态小部件,但据我所知,建议使用一个涉及TextEditingController的有状态小部件。

因此,MyField小部件是有状态的。

MyField Widget-这是根据键入的内容将值存储到控制器的地方。

class MyField extends StatefulWidget {
final String title;
final TextEditingController controller;
const MyField({this.controller, this.title});
@override
_MyFieldState createState() => _MyFieldState();
}
class _MyFieldState extends State<MyField> {
@override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
);
}
}

MyForm Widget-这接受了上述小部件的两个实例,每个实例都有自己的控制器。

这个小部件有助于将文本值传递到MyButton小部件。

class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Stack(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
MyButton(
name: nameController.text,
pass: passController.text,
formKey: formKey)
],
),
);
}
}

MyButton小部件-这个小部件捕获这些文本值,并尝试打印出值,但它当前为空。

class MyButton extends StatelessWidget {
final formKey;
final String name;
final String pass;
const MyButton({Key key, this.formKey, this.name, this.pass}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
// I want to be able to retrieve the text via the controllers for the 2 text fields.
// currently these values are empty which is the issue.
print('name: $name pass: $pass');
},
);
}
}

您可以将值存储在对象文件中,并从项目中的任何其他文件中获取或编辑其值。。例如,在名为user.dart:的文件中

class user {
static String name;
static String pass;
}

然后在任何其他地方导入文件,并根据需要设置或获取其值:

user.name = nameController.text
user.pass = passController.text
print('name: ' + user.name + 'pass: ' + user.pass);

如果你的问题是你想在点击按钮之前显示文本,我认为你可以让你的小部件有状态,然后你可以在文本字段中使用更改事件:

onChanged: (value) {
setState(() { 
user.name = nameController.text;
});}

这是我的尝试。

  • 需要在MyForm类中从"Stack"更改为"Column">
  • 使用"formKey"从TextFormField获取值(虽然我使用了formkey,但我希望从"MyForm"之外控制值,而不是使用"formkey"获取值(
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return MyForm();
}
}
class MyButton extends StatelessWidget {
final formKey;
final String label;
const MyButton({Key key, this.formKey, this.label}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
// I want to be able to retrieve the text via the controllers for the 2 text fields.
// currently these values are empty which is the issue.
print(
'name: ${formKey.currentWidget.child.children[0].controller.text} ');
print(
'pass: ${formKey.currentWidget.child.children[1].controller.text} ');
},
child: Text(label),
);
}
}
class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
MyButton(label: 'Button', formKey: formKey)
],
),
);
}
}
class MyField extends StatefulWidget {
final String title;
final TextEditingController controller;
const MyField({this.controller, this.title});
@override
_MyFieldState createState() => _MyFieldState();
}
class _MyFieldState extends State<MyField> {
@override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
);
}
}

如果你不使用用户键入的文本来更新MyButton小部件的UI状态,你甚至不需要它,你可以访问MyForm小部件中的控制器文本。

class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
RaisedButton(
onPressed() {
print("${nameController.text}");
print("${passController.text}");
}
),
],
),
);
}
}

但是,如果您想在用户键入文本时动态更新MyButton小部件,那么MyForm小部件需要是Statefull,并且必须在每个用户类型事件中重建。

//NOTE: Assuming `MyForm` is a Statefull widget
final nameController = TextEditingController();
final passController = TextEditingController();
@override
void initState() {
// listening the textfield.
nameController.addListener(_controllerListener);
passController.addListener(_controllerListener);
super.initState();
}
void _controllerListener(){
if(mounted)
setState((){});
}
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Stack(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
MyButton(
name: nameController.text,
pass: passController.text,
onPressed: () {
print("${nameController.text} - ${passController.text}");
})
],
),
);
}
}
class MyButton extends StatelessWidget {
final String name;
final String pass;
final VoidCallback onPressed;
const MyButton({Key key, this.onPressed, this.name, this.pass}) : super(key: key);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: this.onPressed,
// updating UI on type event.
child: Text('$name and $pass'),
);
}
}

请将MyForm类更改为class。。。它是如何工作的?你的按钮应该在TextFormField上的每次更改后重建,所以我使用了流生成器和流

class MyForm extends StatelessWidget {
final formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final passController = TextEditingController();
StreamController<int> sc = StreamController<int>();
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
onChanged: () {
sc.add(1);
},
child: Column(
children: [
MyField(
title: 'name',
controller: nameController,
),
MyField(
title: 'pass',
controller: passController,
),
StreamBuilder<int>(
stream: sc.stream,
builder: (context, snapshot) {
return MyButton(
name: nameController.text,
pass: passController.text,
formKey: formKey);
}
)
],
),
);
}
}

最新更新