[英]flutter create dynamic TextField when button click
这是我的要求,当我单击“添加”按钮时,应该生成具有三个 TextField 的动态新卡片,以及如何为每个 TextField 分配动态创建的 TextEditingControllers> 或者是否有其他方法从 TextFields 中获取值?
final name1 = new TextField(
controller: name1Controller,
decoration: InputDecoration(
labelText: 'Full Name', border: OutlineInputBorder()));
final age1 = new TextField(
controller: age1Controler,
keyboardType: TextInputType.number,
decoration:
InputDecoration(labelText: 'Age', border: OutlineInputBorder()));
final studyjob1 = new TextField(
controller: study1Controller,
decoration: InputDecoration(
labelText: 'Study / Job', border: OutlineInputBorder()));
final person1Card = new Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: Padding(
padding: EdgeInsets.only(top: 2.0, left: 6.0, right: 6.0, bottom: 2.0),
child: Column(
children: <Widget>[
Text('Person 1'),
SizedBox(height: 3.0),
name1,
SizedBox(height: 10.0),
age1,
SizedBox(height: 10.0),
studyjob1,
SizedBox(height: 10.0),
],
),
),
);
return Scaffold(
appBar: AppBar(
title: Text('New Entry'),
),
body: SingleChildScrollView(
child: Container(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
person1Card,
SizedBox(
height: 10.0,
),
saveButton
],
),
),
),
),
))
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text('Add entries'),
onPressed: () async {
List<PersonEntry> persons = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SOF(),
),
);
if (persons != null) persons.forEach(print);
},
),
),
);
}
}
class SOF extends StatefulWidget {
@override
_SOFState createState() => _SOFState();
}
class _SOFState extends State<SOF> {
var nameTECs = <TextEditingController>[];
var ageTECs = <TextEditingController>[];
var jobTECs = <TextEditingController>[];
var cards = <Card>[];
Card createCard() {
var nameController = TextEditingController();
var ageController = TextEditingController();
var jobController = TextEditingController();
nameTECs.add(nameController);
ageTECs.add(ageController);
jobTECs.add(jobController);
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('Person ${cards.length + 1}'),
TextField(
controller: nameController,
decoration: InputDecoration(labelText: 'Full Name')),
TextField(
controller: ageController,
decoration: InputDecoration(labelText: 'Age')),
TextField(
controller: jobController,
decoration: InputDecoration(labelText: 'Study/ job')),
],
),
);
}
@override
void initState() {
super.initState();
cards.add(createCard());
}
_onDone() {
List<PersonEntry> entries = [];
for (int i = 0; i < cards.length; i++) {
var name = nameTECs[i].text;
var age = ageTECs[i].text;
var job = jobTECs[i].text;
entries.add(PersonEntry(name, age, job));
}
Navigator.pop(context, entries);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: cards.length,
itemBuilder: (BuildContext context, int index) {
return cards[index];
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: RaisedButton(
child: Text('add new'),
onPressed: () => setState(() => cards.add(createCard())),
),
)
],
),
floatingActionButton:
FloatingActionButton(child: Icon(Icons.done), onPressed: _onDone),
);
}
}
class PersonEntry {
final String name;
final String age;
final String studyJob;
PersonEntry(this.name, this.age, this.studyJob);
@override
String toString() {
return 'Person: name= $name, age= $age, study job= $studyJob';
}
}
您可以为您的controllers
使用List
。
例如:
class PersonControllers {
final TextEditingController name;
final TextEditingController age;
final TextEditingController job;
PersonControllers(this.name, this.age, this.job);
}
然后在你的小部件中
final List<PersonControllers> personControllers = List<PersonControllers>();
在你的initState
personControllers.add(PersonController(TextEditingController(),TextEditingController(),TextEditingController());
创建一个buildCard
方法:
Widget buildCard(PersonControllers controllers){
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: Padding(
padding: EdgeInsets.only(top: 2.0, left: 6.0, right: 6.0, bottom: 2.0),
child: Column(
children: <Widget>[
Text('Person 1'),
SizedBox(height: 3.0),
_buildNameField(controllers.name),
SizedBox(height: 10.0),
_buildAgeField(controllers.age),
SizedBox(height: 10.0),
_buildJobField(controllers.job),
SizedBox(height: 10.0),
],
),
),
);
}
最后在您的build
方法中:
return Scaffold(
appBar: AppBar(
title: Text('New Entry'),
),
body: SingleChildScrollView(
child: Container(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
...personControllers.map((personController) => _buildCard(personController),
SizedBox(
height: 10.0,
),
RaisedButton(
child: Text("Add"),
onPressed: (){
setState((){
personControllers.add(PersonController(
TextEditingController(),
TextEditingController(),
TextEditingController()
});
);
}
),
],
),
),
),
),
))
如果您还想删除表格,请查看此代码可能对某人有帮助
class Test extends StatefulWidget {
const Test({Key? key}) : super(key: key);
@override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
var nameTECs = <int, TextEditingController>{};
var mailTECs = <int, TextEditingController>{};
List<Entry> entries = [];
var item = <int, Widget>{};
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
void didChangeDependencies() {
super.didChangeDependencies();
item.addAll({0: newMethod(context, 0)});
}
ondDone() {
entries.clear();
print(nameTECs.keys.last);
for (int i = 0; i <= nameTECs.keys.last; i++) {
var name = nameTECs[i]?.value.text;
var mail = mailTECs[i]?.value.text;
// print(mailTECs[i]?.value.text);
if (name != null && mail != null) {
entries.add(Entry(name, mail));
}
}
print(entries);
for (int a = 0; a < entries.length; a++) {
print(entries[a].name);
print(entries[a].email);
}
}
newMethod(
BuildContext context,
int index,
) {
var nameController = TextEditingController();
var mailController = TextEditingController();
nameTECs.addAll({index: nameController});
mailTECs.addAll({index: mailController});
return Column(
children: [
Text(index.toString()),
TextFormField(
controller: nameController,
validator: (value) {
return value!.isEmpty ? 'Enter some text' : null;
},
textFieldType: TextFieldType.NAME,
),
TextFormField(
controller: mailController,
validator: (value) {},
// controller: nameCount,
textFieldType: TextFieldType.NAME,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FlatButton(
onTap: () {
item.addAll({item.keys.last+1: newMethod(context, item.keys.last + 1)});
setState(() {});
// }
},
child: Text('Add'),
),
FlatButton(
onTap: () {
setState(() {
item.removeWhere((key, value) => key == index);
nameTECs.removeWhere((key, value) => key == index);
mailTECs.removeWhere((key, value) => key == index);
});
},
child: Text('Remove'),
),
],
),
],
);
}
@override
Widget build(BuildContext context) {
print('build');
return Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: item.length,
itemBuilder: (context, index) {
return item.values.elementAt(index);
}),
// for (int i = 0; i < widgeta.length; i++) widgeta[i],
AppButton(
onTap: () {
if (_formKey.currentState!.validate()) {
ondDone();
// _formKey.currentState!.save();
setState(() {});
}
},
color: appPrimaryColor,
child: Text('save'),
),
Center(
child: Text('Test', textDirection: TextDirection.rtl),
),
],
),
),
),
);
}
}
class Entry {
final String? name;
final String? email;
Entry(
this.name,
this.email,
);
}
class _View4 extends StatefulWidget {
@override
_View4State createState() => _View4State();
}
class _GroupControllers {
TextEditingController name = TextEditingController();
TextEditingController tel = TextEditingController();
TextEditingController address = TextEditingController();
void dispose() {
name.dispose();
tel.dispose();
address.dispose();
}
}
class _View4State extends State<_View4> {
List<_GroupControllers> _groupControllers = [];
List<TextField> _nameFields = [];
List<TextField> _telFields = [];
List<TextField> _addressFields = [];
@override
void dispose() {
for (final controller in _groupControllers) {
controller.dispose();
}
_okController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Dynamic Group Text Field2"),
),
body: Column(
children: [
_addTile(),
Expanded(child: _listView()),
_okButton(context),
],
)),
);
}
Widget _addTile() {
return ListTile(
title: Icon(Icons.add),
onTap: () {
final group = _GroupControllers();
final nameField = _generateTextField(group.name, "name");
final telField = _generateTextField(group.tel, "mobile");
final addressField = _generateTextField(group.address, "address");
setState(() {
_groupControllers.add(group);
_nameFields.add(nameField);
_telFields.add(telField);
_addressFields.add(addressField);
});
},
);
}
TextField _generateTextField(TextEditingController controller, String hint) {
return TextField(
controller: controller,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: hint,
),
);
}
Widget _listView() {
final children = [
for (var i = 0; i < _groupControllers.length; i++)
Container(
margin: EdgeInsets.all(5),
child: InputDecorator(
child: Column(
children: [
_nameFields[i],
_telFields[i],
_addressFields[i],
],
),
decoration: InputDecoration(
labelText: i.toString(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
)
];
return SingleChildScrollView(
child: Column(
children: children,
),
);
}
final _okController = TextEditingController();
Widget _okButton(BuildContext context) {
final textField = TextField(
controller: _okController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
);
final button = ElevatedButton(
onPressed: () async {
final index = int.parse(_okController.text);
String text = "name: ${_groupControllers[index].name.text}\n" +
"tel: ${_groupControllers[index].tel.text}\n" +
"address: ${_groupControllers[index].address.text}\n";
await showMessage(context, text, "Result");
},
child: Text("OK"),
);
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
child: textField,
width: 100,
height: 50,
),
button,
],
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.