小部件Flutter的条件渲染

时间:2020-04-27 22:25:01

标签: flutter dart android-widget flutter-layout

你好,我是新手,已经创建了一个表单生成器应用程序。我正在使用Cloud Firestore作为数据库。我遇到的问题是尝试根据条件呈现特定的小部件。我已经构建了表单,并设置了这样的对象数据:每个项目都有一个包含问题信息的Questions对象列表。我想遍历问题对象并检查问题类型,然后根据该问题类型渲染特定的小部件(例如,多选,图像上传,简短答案等)。理想情况下,它将显示为每页一个问题,并带有下一个按钮。 我想停留在一页上,只在用户按下时调用/显示其他小部件/功能。

问题是我无法通过条件语句来获取小部件来呈现和/或重定向。现在,我为每个循环设置了一个简单的语句,嵌套了一个switch语句,但是由于迭代一直进行到页面永远不会呈现的最后一个对象为止。我的目标是在按下按钮时添加一个按钮,以继续迭代。

我有一个视图项目页面,该页面设置了GetProject对象,然后调用必要的类函数以从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(

    );
  }
}

3 个答案:

答案 0 :(得分:2)

似乎您的代码中几乎没有需要解决的问题,因此这可能并不是您真正想要实现的,但是它将为您提供一般的指导。

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(),因此您必须决定在哪里调用它。

答案 1 :(得分:1)

非常有趣的问题!

我使用FutureBuilder发布了一些代码。当您按下标有“下一个”的按钮时,将显示一个基于随机数的小部件(随机数可能是数据库结果)

谢谢。

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

          }
      );
  }
}

答案 2 :(得分:-1)

这段代码非常适合我,请试试

Container(
         child: (controller.isPlaying == true) ?  Text(controller.message) :  Text(controller.message),,
       )