Генерация виджетов в просмотре страниц на основе условной логики - PullRequest
0 голосов
/ 31 марта 2020

В настоящее время сталкивается с проблемой условных логи c и виджета PageView. Допустим, что PageView будет динамически генерировать 3 страницы. На этих 3 страницах будут генерироваться разные виджеты. Одним из виджетов является кнопка (называемая «Next»), которая является PageController, но этот виджет должен быть заменен виджетом кнопки, который должен представлять (называемый «Submit») всю форму (PageView упакован в формы).

Кажется очевидным, просто напишите условную логику c, которая сравнивает текущую страницу PageView с длиной PageView (PageView заполняется списком, поэтому легко получить длина). Затем переключайте виджеты, когда выполняются правильные условия: когда текущая страница равна 3, измените виджет. К сожалению, PageView отображает кнопку «Далее» на каждой странице. Так что только когда я доберусь до последней страницы и затем снова нажму «Далее», она изменится на «Отправить». Предполагается, что это «Отправить», когда пользователь попадает на последнюю страницу.

const int TRIVIA_STARTING_TIME = 10;

class TriviaOneForm extends StatefulWidget {
  final UserRepository _userRepository;

  TriviaOneForm({Key key, @required UserRepository userRepository})
      : assert(userRepository != null),
        _userRepository = userRepository,
        super(key: key);

  State<TriviaOneForm> createState() => _TriviaOneFormState();
}

class _TriviaOneFormState extends State<TriviaOneForm> {
  final TextEditingController _answerController = TextEditingController();

  UserRepository get _userRepository => widget._userRepository;

  TriviaOneBloc _triviaOneBloc;
  PageController _pageController;

  Timer _timer;

  bool _isLoadingScreen;
  bool _isNextOrSubmitButton;
  int _start;
  int _indexOfCarouselItem;
  List<int> _selectedValList;

  List _triviaDataList;

  @override
  void initState() {
    super.initState();
    _isLoadingScreen = true;
    _getTriviaData();
    _pageController = PageController();
    _indexOfCarouselItem = 0;
    _isNextOrSubmitButton = true;
    _selectedValList = [0, 0, 0, 0, 0];
    _triviaDataList = [];
    _start = TRIVIA_STARTING_TIME;
    _triviaOneBloc = BlocProvider.of<TriviaOneBloc>(context);
    _answerController.addListener(_onAnswerChanged);
  }

  @override
  void dispose() {
    if (_timer != null) {
      _timer.cancel();
    }
    _pageController.dispose();
    super.dispose();
  }

  void startTimer() {
    const oneSec = const Duration(seconds: 1);
    _timer = new Timer.periodic(
      oneSec,
      (Timer timer) => setState(
        () {
          if (_start < 1) {
            timer.cancel();
          } else {
            _start = _start - 1;
          }
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<TriviaOneBloc, TriviaOneState>(
      listener: (context, state) {
        if (state.isFailure) {
          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Text('Submition Failure'),
                    Icon(Icons.error)
                  ],
                ),
                backgroundColor: Colors.red,
              ),
            );
        }
        if (state.isSubmitting) {
          Scaffold.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(
                content: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Text('Submitting Answers...'),
                  ],
                ),
              ),
            );
        }
        if (state.isSuccess) {
          BlocProvider.of<TriviaOneBloc>(context).add(Submitted());
        }
      },
      child: BlocBuilder<TriviaOneBloc, TriviaOneState>(
        builder: (context, state) {
          return _isLoadingScreen
              ? _displayLoadScreen()
              : Padding(
                  padding: EdgeInsets.all(20.0),
                  child: Form(
                    child: PageView(
                      physics: NeverScrollableScrollPhysics(),
                      controller: _pageController,
                      reverse: false,
                      scrollDirection: Axis.horizontal,
                      children: _triviaDataList.map<Widget>((triviaData) {
                        return ListView(
                          shrinkWrap: true,
                          children: <Widget>[
                            Text(triviaData.getQuestion),
                            ListView(
                              shrinkWrap: true,
                              children: triviaData.getAnswers
                                  .map<Widget>((triviaAnswer) {
                                int index =
                                    triviaData.getAnswers.indexOf(triviaAnswer);
                                return ListTile(
                                  title: Text(triviaAnswer.getAnswer),
                                  leading: Radio(
                                    value: index,
                                    groupValue:
                                        _selectedValList[_indexOfCarouselItem],
                                    onChanged: (int value) {
                                      setState(() {
                                        print(value);
                                        _selectedValList[_indexOfCarouselItem] =
                                            value;
                                      });
                                    },
                                  ),
                                );
                              }).toList(),
                            ),
                            _isNextOrSubmitButton ? _nextButton() : _submitButton(),
                            RaisedButton(
                              onPressed: () {
                                startTimer();
                              },
                              child: Text('Start'),
                            ),
                            Text('$_start'),
                          ],
                        );
                      }).toList(),
                    ),
                  ),
                );
        },
      ),
    );
  }

  Widget _triviaControlButton(PageController pageController) {
    if (0 < _triviaDataList.length) {
      return RaisedButton(
        child: Text('Next'),
        onPressed: () {
          pageController.nextPage(
              duration: Duration(seconds: 1), curve: Curves.easeInOut);
          print('Next');
        },
      );
    } else if (pageController.page.toInt() == _triviaDataList.length) {
      return RaisedButton(
        child: Text('Submit'),
        onPressed: () {
          print('Submit');
        },
      );
    } else {
      return RaisedButton(
        child: Text('Error'),
        onPressed: () {
          print('Error');
        },
      );
    }
  }

  Widget _displayLoadScreen() {
    return Container(
      alignment: Alignment(0.0, 0.0),
      child: CircularProgressIndicator(),
    );
  }

  void _onAnswerChanged() {
    _triviaOneBloc.add(AnswerChanged(answer: _answerController.text));
  }

  void _getTriviaData() async {
    var data = _userRepository.retrieveTriviaData();
    // Await trivia data to be retrieved from firebase
    await data.getDocuments().then((collection) {
      collection.documents.forEach((document) {
        TriviaData triviaData = TriviaData();
        List<TriviaAnswer> triviaAnswerList = List<TriviaAnswer>();
        // Iterate through all of the answers for a question
        // Create a list of TriviaAnswer objects to hold key and value
        document.data['answers'].forEach((key, value) {
          TriviaAnswer triviaAnswer = TriviaAnswer();
          triviaAnswer.setAnswer = key;
          triviaAnswer.setAnswerValue = value;
          triviaAnswerList.add(triviaAnswer);
        });
        // Assign question String and answer List to TriviaData
        // Add all data to data list
        triviaData.setAnswers = triviaAnswerList;
        triviaData.setQuestion = document.data['question'];
        _triviaDataList.add(triviaData);
      });
    });
    setState(() {
      _isLoadingScreen = false;
    });
  }

  Widget _nextButton() {
    return RaisedButton(
      child: Text('Next'),
      onPressed: () {
        if (_indexOfCarouselItem < _triviaDataList.length) {
          _pageController.nextPage(
              duration: const Duration(milliseconds: 100),
              curve: Curves.easeInOut);
          setState(() {
            _start = TRIVIA_STARTING_TIME;
            _indexOfCarouselItem += 1;
          });
        }
        if (_indexOfCarouselItem == _triviaDataList.length) {
          Future.delayed(const Duration(seconds: 0), () {
            setState(() {
              _isNextOrSubmitButton = false;
            });
          });
        }
        try {
          if (_timer != null || !_timer.isActive) {
            startTimer();
          }
        } catch (_) {
          print('Error: Timer is already disabled');
        }
      },
    );
  }

  Widget _submitButton() {
    return RaisedButton(
      child: Text('Submit'),
      onPressed: () {
        print(_selectedValList);
        _userRepository.storeTriviaToFirebase();
        setState(() {
          if (_timer != null || _timer.isActive) {
            _timer.cancel();
          }
        });
      },
    );
  }
}

РЕДАКТИРОВАТЬ 1: Это обновленный код, который я использую для кнопки для заполнения в PageView. Я устанавливаю строку в начальное значение «Далее», а затем обновляю ее, когда _indexOfCarouselItem + 2 == _triviaDataList.length имеет значение true. Обновленное значение будет «Отправить», когда условие будет выполнено.

Widget _triviaControlButton() {
    return RaisedButton(
      child: Text(buttonText),
      onPressed: () {
        _pageController.nextPage(
            duration: const Duration(milliseconds: 100),
            curve: Curves.easeInOut);
        if (_indexOfCarouselItem + 2 == _triviaDataList.length) {
          setState(() {
            buttonText = "Submit";
          });
        }
        if (_indexOfCarouselItem < _triviaDataList.length) {
          setState(() {
            _start = TRIVIA_STARTING_TIME;
            _indexOfCarouselItem += 1;
          });
        }
        print(_indexOfCarouselItem);
        print(_triviaDataList.length);
      },
    );
  }

1 Ответ

1 голос
/ 31 марта 2020

Я сейчас на телефоне, поэтому не могу гарантировать, что код, который я опубликую, в порядке, но вы поймете.

Во-первых: я не думаю, что вам нужны 2 кнопки, если они равны по размеру et c. так что вы можете реализовать что-то вроде этого:

child: Text( _indexOfCarouselItem += 1 !=  _triviaDataList.length
 ? 'Next' : 'Submit')

И затем использовать те же логи c в onPressed:

onPressed() {
   _indexOfCarouselItem += 1 != _triviaDataList.length ? doSomethibg : doSomethingDifferent;
}

Редактировать: Хорошо, если я правильно понимаю проблему прямо сейчас это из-за перехода кнопка говорит "Отправить", но вопросов пока нет? Если это тот случай, который вы можете, как вы сказали, добавить задержку, но я думаю, что лучший подход - это связать текст кнопки с вопросом. Я имею в виду, что вы можете сохранить фактические логи c (потому что это работает) и добавить что-то вроде этого:

child: Text (_indexOfCarouselItem + = 1! = _TriviaDataList.length && questionText! = "" ? 'Next': 'Submit')

Этот лог c может применяться в блоке if ... else ...

Edit 2 : попробуйте это:

Widget _triviaControlButton() {
    return RaisedButton(
      child: Text(buttonText),
      onPressed: () {
        _pageController.nextPage(
            duration: const Duration(milliseconds: 100),
            curve: Curves.easeInOut);
        if (_indexOfCarouselItem < _triviaDataList.length) {
          setState(() {
            _start = TRIVIA_STARTING_TIME;
            _indexOfCarouselItem += 1;
          });
if (_indexOfCarouselItem == _triviaDataList.length) {
          setState(() {
            buttonText = "Submit";
          });
        }
      },
    );
  }
...