Widgets Flutter 的条件渲染
Conditional Rendering of Widgets Flutter
您好,我是 Flutter 新手,我创建了一个表单生成器应用程序。我正在使用 Cloud Firestore 作为我的数据库。我遇到的问题是尝试根据条件呈现特定的小部件。我已经构建了表单并像这样设置了对象数据:每个项目都有一个包含问题信息的问题对象列表。我想遍历问题对象并检查问题类型,然后根据该问题类型呈现某个小部件(例如多项选择、图像上传、简短回答等)。理想情况下,它将显示为每页一个问题,并带有下一个按钮。 我想停留在一个页面上,而只是 call/display 其他 widgets/functions 用户按下一个。
问题是我无法让小部件呈现 and/or 通过条件语句重定向。现在,我为每个循环设置了一个简单的循环,其中嵌套了一个 switch 语句,但是由于迭代一直持续到它成为页面永远不会呈现的最后一个对象。我的目标是在按下时添加一个按钮将继续迭代。
我有一个查看项目页面,它设置了 GetProject 对象,然后调用必要的 class 函数从 firestore 获取数据。
class Questions{
final String question;
final String number;
final String type;
Questions({this.question, this.number, this.type});
List<String> answers = new List();
}
class GetProject {
final String docID;
final String title;
GetProject({this.docID, this.title});
List<Questions> questions = new List();
//....Class Functions below not relevant
}
这是我目前的查看项目页面
import 'package:flutter/material.dart';
import '../../models/project.dart';
import '../../Services/getproject.dart';
import 'textquestion.dart';
import 'multiplechoicequestion.dart';
import 'UserLocationInfo.dart';
import 'shortanswerquestion.dart';
class ViewProject extends StatefulWidget {
final String docIDref;
final String title;
ViewProject({this.docIDref, this.title});
@override
_ViewProjectState createState() => _ViewProjectState();
}
class _ViewProjectState extends State<ViewProject> {
@override
Widget build(BuildContext context) {
GetProject project = new GetProject(docID: widget.docIDref, title: widget.title);
project.getdataFromProject();
project.questions.forEach((e){
var type = e.type;
switch(type){
case 'TextInputItem':
return new TextQuestionWidget(question: e);
case 'MultipleChoice':
return new MultQuestionWidget(question: e);
case 'ShortAnswer':
return new ShortAnswerQuestion(question: e);
case 'UserLocation':
return new UserLocationInfo(question: e);
}
return null;
});
//project.printproj();
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
child: Card(
child: ListTile(
title: Text('Print Values to debug console'),
subtitle: Text(''),
trailing: Icon(Icons.arrow_forward_ios),
onTap: () {
project.printproj();
}
),
),
),
);
}
}
这是被调用的小部件的示例
import '../../Services/getproject.dart';
class UserLocationInfo extends StatefulWidget {
final Questions question;
UserLocationInfo({this.question});
@override
_UserLocationInfoState createState() => _UserLocationInfoState();
}
class _UserLocationInfoState extends State<UserLocationInfo> {
@override
Widget build(BuildContext context) {
return Container(
);
}
}
您的代码中似乎几乎没有什么问题需要解决,因此这可能不是您真正想要实现的目标,但它会为您提供从这里开始的大致方向。
class ViewProject extends StatefulWidget {
final String docIDref;
final String title;
ViewProject({this.docIDref, this.title});
@override
_ViewProjectState createState() => _ViewProjectState();
}
class _ViewProjectState extends State<ViewProject> {
GetProject project;
int _currentPage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
// when there is no questions(still loading), show a progress indicator
body: project.questions == null
? Center(child: CircularProgressIndicator())
// IndexedStack will hide all children except the "index"th child
: IndexedStack(
index: _currentPage,
children: project.questions
.map((question) => _question(question))
.toList(),
),
);
}
@override
void initState() {
project = GetProject(docID: widget.docIDref, title: widget.title);
super.initState();
}
// Call this function when you want to move to the next page
void goToNextPage() {
setState(() {
_currentPage++;
});
}
Future<void> _getQuestions() async {
// you mentioned you use firebase for database, so
// you have to wait for the data to be loaded from the network
await project.getdataFromProject();
setState(() {});
}
Widget _question(Questions question) {
switch (question.type) {
case 'TextInputItem':
return TextQuestionWidget(question: e);
case 'MultipleChoice':
return MultQuestionWidget(question: e);
case 'ShortAnswer':
return ShortAnswerQuestion(question: e);
case 'UserLocation':
return UserLocationInfo(question: e);
}
}
}
我不确定您想在哪里调用 goToNextPage(),所以您必须决定在哪里调用它。
非常有趣的问题!!
我使用 FutureBuilder 发布了一些代码。当您按下标记为 'NEXT' 的按钮时,将根据随机数显示一个小部件(随机数可以是数据库结果)
谢谢。
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
@override
Future<int> _newRandomNumber() async{
print("_newRandomNumber");
return await Random().nextInt(4);
}
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: AppBar(title: Text("Random Widget")),
body: Center(child:
FutureBuilder(
initialData: 0,
future:_newRandomNumber(),
builder: (context, snapshot) {
if(snapshot.hasData){
return getRandomWidget(snapshot.data);
}
}
)
)),
);
}
Widget getRandomWidget(int randomNumber) {
switch(randomNumber){
case 0:
return Column(children: <Widget>[
Text("TextInputItem",textScaleFactor: 4),
getNextButton()
]);
break;
case 1:
return Column(children: <Widget>[
Text("MultipleChoice",textScaleFactor: 4),
getNextButton()
]);
break;
case 2:
return Column(children: <Widget>[
Text("ShortAnswer",textScaleFactor: 4),
getNextButton()
]);
break;
case 3:
return Column(children: <Widget>[
Text("UserLocation",textScaleFactor: 4),
getNextButton()
]);
break;
}
}
Widget getNextButton(){
return RaisedButton(
child: Text("NEXT"),
color: Colors.red,
onPressed: () {
setState(() {
_newRandomNumber();
});
}
);
}
}
您好,我是 Flutter 新手,我创建了一个表单生成器应用程序。我正在使用 Cloud Firestore 作为我的数据库。我遇到的问题是尝试根据条件呈现特定的小部件。我已经构建了表单并像这样设置了对象数据:每个项目都有一个包含问题信息的问题对象列表。我想遍历问题对象并检查问题类型,然后根据该问题类型呈现某个小部件(例如多项选择、图像上传、简短回答等)。理想情况下,它将显示为每页一个问题,并带有下一个按钮。 我想停留在一个页面上,而只是 call/display 其他 widgets/functions 用户按下一个。
问题是我无法让小部件呈现 and/or 通过条件语句重定向。现在,我为每个循环设置了一个简单的循环,其中嵌套了一个 switch 语句,但是由于迭代一直持续到它成为页面永远不会呈现的最后一个对象。我的目标是在按下时添加一个按钮将继续迭代。
我有一个查看项目页面,它设置了 GetProject 对象,然后调用必要的 class 函数从 firestore 获取数据。
class Questions{
final String question;
final String number;
final String type;
Questions({this.question, this.number, this.type});
List<String> answers = new List();
}
class GetProject {
final String docID;
final String title;
GetProject({this.docID, this.title});
List<Questions> questions = new List();
//....Class Functions below not relevant
}
这是我目前的查看项目页面
import 'package:flutter/material.dart';
import '../../models/project.dart';
import '../../Services/getproject.dart';
import 'textquestion.dart';
import 'multiplechoicequestion.dart';
import 'UserLocationInfo.dart';
import 'shortanswerquestion.dart';
class ViewProject extends StatefulWidget {
final String docIDref;
final String title;
ViewProject({this.docIDref, this.title});
@override
_ViewProjectState createState() => _ViewProjectState();
}
class _ViewProjectState extends State<ViewProject> {
@override
Widget build(BuildContext context) {
GetProject project = new GetProject(docID: widget.docIDref, title: widget.title);
project.getdataFromProject();
project.questions.forEach((e){
var type = e.type;
switch(type){
case 'TextInputItem':
return new TextQuestionWidget(question: e);
case 'MultipleChoice':
return new MultQuestionWidget(question: e);
case 'ShortAnswer':
return new ShortAnswerQuestion(question: e);
case 'UserLocation':
return new UserLocationInfo(question: e);
}
return null;
});
//project.printproj();
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
child: Card(
child: ListTile(
title: Text('Print Values to debug console'),
subtitle: Text(''),
trailing: Icon(Icons.arrow_forward_ios),
onTap: () {
project.printproj();
}
),
),
),
);
}
}
这是被调用的小部件的示例
import '../../Services/getproject.dart';
class UserLocationInfo extends StatefulWidget {
final Questions question;
UserLocationInfo({this.question});
@override
_UserLocationInfoState createState() => _UserLocationInfoState();
}
class _UserLocationInfoState extends State<UserLocationInfo> {
@override
Widget build(BuildContext context) {
return Container(
);
}
}
您的代码中似乎几乎没有什么问题需要解决,因此这可能不是您真正想要实现的目标,但它会为您提供从这里开始的大致方向。
class ViewProject extends StatefulWidget {
final String docIDref;
final String title;
ViewProject({this.docIDref, this.title});
@override
_ViewProjectState createState() => _ViewProjectState();
}
class _ViewProjectState extends State<ViewProject> {
GetProject project;
int _currentPage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
// when there is no questions(still loading), show a progress indicator
body: project.questions == null
? Center(child: CircularProgressIndicator())
// IndexedStack will hide all children except the "index"th child
: IndexedStack(
index: _currentPage,
children: project.questions
.map((question) => _question(question))
.toList(),
),
);
}
@override
void initState() {
project = GetProject(docID: widget.docIDref, title: widget.title);
super.initState();
}
// Call this function when you want to move to the next page
void goToNextPage() {
setState(() {
_currentPage++;
});
}
Future<void> _getQuestions() async {
// you mentioned you use firebase for database, so
// you have to wait for the data to be loaded from the network
await project.getdataFromProject();
setState(() {});
}
Widget _question(Questions question) {
switch (question.type) {
case 'TextInputItem':
return TextQuestionWidget(question: e);
case 'MultipleChoice':
return MultQuestionWidget(question: e);
case 'ShortAnswer':
return ShortAnswerQuestion(question: e);
case 'UserLocation':
return UserLocationInfo(question: e);
}
}
}
我不确定您想在哪里调用 goToNextPage(),所以您必须决定在哪里调用它。
非常有趣的问题!!
我使用 FutureBuilder 发布了一些代码。当您按下标记为 'NEXT' 的按钮时,将根据随机数显示一个小部件(随机数可以是数据库结果)
谢谢。
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
@override
Future<int> _newRandomNumber() async{
print("_newRandomNumber");
return await Random().nextInt(4);
}
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: AppBar(title: Text("Random Widget")),
body: Center(child:
FutureBuilder(
initialData: 0,
future:_newRandomNumber(),
builder: (context, snapshot) {
if(snapshot.hasData){
return getRandomWidget(snapshot.data);
}
}
)
)),
);
}
Widget getRandomWidget(int randomNumber) {
switch(randomNumber){
case 0:
return Column(children: <Widget>[
Text("TextInputItem",textScaleFactor: 4),
getNextButton()
]);
break;
case 1:
return Column(children: <Widget>[
Text("MultipleChoice",textScaleFactor: 4),
getNextButton()
]);
break;
case 2:
return Column(children: <Widget>[
Text("ShortAnswer",textScaleFactor: 4),
getNextButton()
]);
break;
case 3:
return Column(children: <Widget>[
Text("UserLocation",textScaleFactor: 4),
getNextButton()
]);
break;
}
}
Widget getNextButton(){
return RaisedButton(
child: Text("NEXT"),
color: Colors.red,
onPressed: () {
setState(() {
_newRandomNumber();
});
}
);
}
}