Условный рендеринг виджетов Флаттер - PullRequest
0 голосов
/ 28 апреля 2020

Здравствуйте, я новичок в трепетании и создал приложение для создания форм. Я использую Cloud Firestore в качестве базы данных. Проблема, с которой я сталкиваюсь - это попытка отрисовки определенных c виджетов на основе условия. Я построил форму и настроил данные объекта следующим образом: у каждого проекта есть список объектов вопросов, содержащих информацию о вопросе. Я хочу перебрать объекты вопроса и проверить тип вопроса, а затем на основе этого типа вопроса отобразить определенный виджет (например, множественный выбор, загрузка изображений, короткий ответ и т. Д. c). В идеале это будет отображаться как один вопрос на странице с помощью следующей кнопки. Я хотел бы остаться на одной странице и просто вызывать / отображать другие виджеты / функции, когда пользователь нажимает следующую.

Проблема в том, что я не могу заставить виджеты отображаться и / или перенаправить с помощью условного оператора. Прямо сейчас я установил простой для каждого l oop с оператором switch, вложенным внутрь, однако, так как итерация продолжается, пока это не последний объект, который страницы никогда не визуализируют. Моя цель - добавить кнопку при нажатии, чтобы продолжить итерацию.

У меня есть страница проекта представления, которая устанавливает объект GetProject и затем вызывает необходимые функции класса для получения данных из хранилища.

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(

    );
  }
}

Ответы [ 2 ]

1 голос
/ 28 апреля 2020

Очень интересный вопрос !!

Я разместил код с помощью FutureBuilder. Когда вы нажимаете sh кнопку с надписью «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();
            });

          }
      );
  }
}

1 голос
/ 28 апреля 2020

Кажется, что у вас есть несколько проблем, которые необходимо решить в вашем коде, поэтому это может быть не совсем то, чего вы хотите достичь, но это даст вам общие указания к go отсюда.

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 (), поэтому вам придется решить, где его вызвать.

...