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();
            });

          }
      );
  }
}