如何在 ExpansionTile Flutter 中使用动态 TextField 控制器
How to use dynamic TextField Controller inside ExpansionTile Flutter
作为 Flutter 的新手,我创建了一个 ExpansionTile(见下面的截图)并添加了 EditField
作为 Child.
这里 ExpansioTile
和评论 EditField
是根据服务器响应动态创建的。
每个ExpansionTile
里面会有多个TextFields
现在如何动态添加 TextFieldController
并在单击按钮时获取所有值?
ExpansionTile 代码
FutureBuilder(
future: _fetchQuestions(),
builder: (context, AsyncSnapshot snapshot){
if (snapshot.hasError) {
return Text('Error ${snapshot.error}');
}
else if (snapshot.hasData) {
return new Padding(
padding: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 0.0),
child: Container(
child: PageView.builder(
physics: new NeverScrollableScrollPhysics(),
controller: _pageController,
itemCount: snapshot.data[0].auditAreas.length,
onPageChanged: (int index) {
print('@@ on page changed $index');
},
itemBuilder: (BuildContext context, int index) {
print('@@ index '+index.toString());
List<QuestionGroups> listQuestionsGrp = snapshot.data[0].auditAreas[index].questionGroups;
print('@@ question grp list size == '+listQuestionsGrp.length.toString());
List<Widget> list = new List<Widget>();
for (int i=0; i<listQuestionsGrp.length; i++){
bloc.newFields();
List<Widget> listItemWidgets = new List<Widget>();
// below list(listAuditQues) is used to get the questions from question groups
List<AuditQuestions> listAuditQues = listQuestionsGrp[i].auditQuestions;
for (int j=0; j<listAuditQues.length; j++){
print('@ audit question id == '+listAuditQues[j].auditQuestionId.toString());
// _mapController.map(listAuditQues[j].auditQuestionId, _textController);
// _controllers.add(TextEditingController());
List<AuditQuestionAnswers> listAuditQuestAns = listAuditQues[j].auditQuestionAnswers;
print('@@ list of question and answers used for radio buttons == '+listAuditQuestAns.length.toString());
List<Widget> listTitleOfRadioButtons = new List<Widget>();
for (int k=0; k<listAuditQuestAns.length; k++){
// here have to get the list of radio button text and append below inside the column
List<AuditQuestionAnswerOptionParameters> listQuesAnsParameter = listAuditQuestAns[k].auditQuestionAnswerOptionParameters;
print('@@ list question answer list size == '+listQuesAnsParameter.length.toString());
List<Widget> listRadioButtons = new List<Widget>();
for (int m=0; m<listQuesAnsParameter.length; m++){
listRadioButtons.add(
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Radio(value: 0, groupValue: null, onChanged: null, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,),
new Text(listQuesAnsParameter[m].answerOptionParameterTitle,style: TextStyle(
fontSize: 12.0
))
],
)
);
}
listTitleOfRadioButtons.add(
Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Container(
margin: EdgeInsets.fromLTRB(10.0, 4.0, 0.0, 4.0),
child: Text(listAuditQuestAns[k].auditEntityTitle,
style: TextStyle(fontSize: 13.5),),
),
),
Row(
children: listRadioButtons,
)
],
)
);
}
// Here adding expansion item content
listItemWidgets.add(
Column(
children: <Widget>[
Row(
// mainAxisAlignment: message.author == username ? MainAxisAlignment.end : MainAxisAlignment.start,
//this will determine if the message should be displayed left or right
children: [
Flexible(
//Wrapping the container with flexible widget
child: Container(
padding: EdgeInsets.all(6.0),
margin: EdgeInsets.all(4.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.0),
border: Border.all(color: Colors.black)
),
child: Row(
children: <Widget>[
Flexible(
//We only want to wrap the text message with flexible widget
child: Container(
child: Text(
listAuditQues[j].title,
)
)
),
],
)
),
)
]
),
Column(
children: listTitleOfRadioButtons
),
Container(
height: 80,
margin: EdgeInsets.all(4.0),
child: new ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 80.0,
),
child: new Scrollbar(
child: new SingleChildScrollView(
scrollDirection: Axis.vertical,
reverse: true,
child: SizedBox(
height: 80.0,
child: new TextFormField(
// controller: _controllers[j],
maxLines: 60,
decoration: new InputDecoration(
labelText: "Comment",
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.black, width: 0.8)),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.black, width: 0.8)),
),
),
),
),
),
),
),
new Container(
margin: EdgeInsets.all(4.0),
padding: EdgeInsets.fromLTRB(2.0, 4.0, 0.0, 0.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: (){
print('@@ index of pager $index');
print('@@ index of main lopp $i');
print('@@ index of lopp $j');
},
child: new Icon(Icons.camera_alt,
size: 22.0, color: Colors.black),
),
new Icon(Icons.attach_file,
size: 22.0, color: Colors.black),
new Text("(4)", style: TextStyle(fontSize: 12.0))
],
),
),
Container(
margin: EdgeInsets.all(4.0),
child: Divider(height: 4.0,color: Colors.black),
)
],
)
);
}
// Main Title of expansion list adding here
list.add(customExpansionTile.ExpansionTile(
headerBackgroundColor: Colors.grey,
backgroundColor: Colors.white,
iconColor: Colors.black,
title: Text(listQuestionsGrp[i].title, style: TextStyle(
fontSize: 14.0
)),
children: listItemWidgets
));
}
return new ListView(
children: list,
);
// return _buidlExpnsionListTile(snapshot.data[0]);
/*List<AuditAreas> auditAreaList = snapshot.data[index].auditAreas;
print('@@ audit area list size == ${auditAreaList.length}');
return Text('Screen index == '+index.toString());*/
},
),
),
);
}
else{
return CircularProgressIndicator();
}
},
)
请帮帮我..
初始化它:
TextEditingController controller;
在初始状态:
@override
initState() {
super.initState();
controller = new TextEditingController();
}
TextFormField 中的控制器示例:
new TextFormField(
validator: (senha) =>
senha.isEmpty ? 'Por favor insira sua senha' : null,
onSaved: (senha) => _pass = senha,
obscureText: true,
textAlign: TextAlign.start,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0)),
filled: true,
hintText: 'Senha',
),
controller: controller,
),
要访问 TextFormField 文本,只需 controller.text
作为 Flutter 的新手,我创建了一个 ExpansionTile(见下面的截图)并添加了 EditField
作为 Child.
这里 ExpansioTile
和评论 EditField
是根据服务器响应动态创建的。
每个ExpansionTile
里面会有多个TextFields
现在如何动态添加 TextFieldController
并在单击按钮时获取所有值?
ExpansionTile 代码
FutureBuilder(
future: _fetchQuestions(),
builder: (context, AsyncSnapshot snapshot){
if (snapshot.hasError) {
return Text('Error ${snapshot.error}');
}
else if (snapshot.hasData) {
return new Padding(
padding: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 0.0),
child: Container(
child: PageView.builder(
physics: new NeverScrollableScrollPhysics(),
controller: _pageController,
itemCount: snapshot.data[0].auditAreas.length,
onPageChanged: (int index) {
print('@@ on page changed $index');
},
itemBuilder: (BuildContext context, int index) {
print('@@ index '+index.toString());
List<QuestionGroups> listQuestionsGrp = snapshot.data[0].auditAreas[index].questionGroups;
print('@@ question grp list size == '+listQuestionsGrp.length.toString());
List<Widget> list = new List<Widget>();
for (int i=0; i<listQuestionsGrp.length; i++){
bloc.newFields();
List<Widget> listItemWidgets = new List<Widget>();
// below list(listAuditQues) is used to get the questions from question groups
List<AuditQuestions> listAuditQues = listQuestionsGrp[i].auditQuestions;
for (int j=0; j<listAuditQues.length; j++){
print('@ audit question id == '+listAuditQues[j].auditQuestionId.toString());
// _mapController.map(listAuditQues[j].auditQuestionId, _textController);
// _controllers.add(TextEditingController());
List<AuditQuestionAnswers> listAuditQuestAns = listAuditQues[j].auditQuestionAnswers;
print('@@ list of question and answers used for radio buttons == '+listAuditQuestAns.length.toString());
List<Widget> listTitleOfRadioButtons = new List<Widget>();
for (int k=0; k<listAuditQuestAns.length; k++){
// here have to get the list of radio button text and append below inside the column
List<AuditQuestionAnswerOptionParameters> listQuesAnsParameter = listAuditQuestAns[k].auditQuestionAnswerOptionParameters;
print('@@ list question answer list size == '+listQuesAnsParameter.length.toString());
List<Widget> listRadioButtons = new List<Widget>();
for (int m=0; m<listQuesAnsParameter.length; m++){
listRadioButtons.add(
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Radio(value: 0, groupValue: null, onChanged: null, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,),
new Text(listQuesAnsParameter[m].answerOptionParameterTitle,style: TextStyle(
fontSize: 12.0
))
],
)
);
}
listTitleOfRadioButtons.add(
Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Container(
margin: EdgeInsets.fromLTRB(10.0, 4.0, 0.0, 4.0),
child: Text(listAuditQuestAns[k].auditEntityTitle,
style: TextStyle(fontSize: 13.5),),
),
),
Row(
children: listRadioButtons,
)
],
)
);
}
// Here adding expansion item content
listItemWidgets.add(
Column(
children: <Widget>[
Row(
// mainAxisAlignment: message.author == username ? MainAxisAlignment.end : MainAxisAlignment.start,
//this will determine if the message should be displayed left or right
children: [
Flexible(
//Wrapping the container with flexible widget
child: Container(
padding: EdgeInsets.all(6.0),
margin: EdgeInsets.all(4.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.0),
border: Border.all(color: Colors.black)
),
child: Row(
children: <Widget>[
Flexible(
//We only want to wrap the text message with flexible widget
child: Container(
child: Text(
listAuditQues[j].title,
)
)
),
],
)
),
)
]
),
Column(
children: listTitleOfRadioButtons
),
Container(
height: 80,
margin: EdgeInsets.all(4.0),
child: new ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 80.0,
),
child: new Scrollbar(
child: new SingleChildScrollView(
scrollDirection: Axis.vertical,
reverse: true,
child: SizedBox(
height: 80.0,
child: new TextFormField(
// controller: _controllers[j],
maxLines: 60,
decoration: new InputDecoration(
labelText: "Comment",
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.black, width: 0.8)),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.black, width: 0.8)),
),
),
),
),
),
),
),
new Container(
margin: EdgeInsets.all(4.0),
padding: EdgeInsets.fromLTRB(2.0, 4.0, 0.0, 0.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: (){
print('@@ index of pager $index');
print('@@ index of main lopp $i');
print('@@ index of lopp $j');
},
child: new Icon(Icons.camera_alt,
size: 22.0, color: Colors.black),
),
new Icon(Icons.attach_file,
size: 22.0, color: Colors.black),
new Text("(4)", style: TextStyle(fontSize: 12.0))
],
),
),
Container(
margin: EdgeInsets.all(4.0),
child: Divider(height: 4.0,color: Colors.black),
)
],
)
);
}
// Main Title of expansion list adding here
list.add(customExpansionTile.ExpansionTile(
headerBackgroundColor: Colors.grey,
backgroundColor: Colors.white,
iconColor: Colors.black,
title: Text(listQuestionsGrp[i].title, style: TextStyle(
fontSize: 14.0
)),
children: listItemWidgets
));
}
return new ListView(
children: list,
);
// return _buidlExpnsionListTile(snapshot.data[0]);
/*List<AuditAreas> auditAreaList = snapshot.data[index].auditAreas;
print('@@ audit area list size == ${auditAreaList.length}');
return Text('Screen index == '+index.toString());*/
},
),
),
);
}
else{
return CircularProgressIndicator();
}
},
)
请帮帮我..
初始化它:
TextEditingController controller;
在初始状态:
@override
initState() {
super.initState();
controller = new TextEditingController();
}
TextFormField 中的控制器示例:
new TextFormField(
validator: (senha) =>
senha.isEmpty ? 'Por favor insira sua senha' : null,
onSaved: (senha) => _pass = senha,
obscureText: true,
textAlign: TextAlign.start,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0)),
filled: true,
hintText: 'Senha',
),
controller: controller,
),
要访问 TextFormField 文本,只需 controller.text