В настоящее время сталкивается с проблемой условных логи 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);
},
);
}