目前面临条件逻辑和 PageView 小部件的问题。假设 PageView 将动态生成 3 个页面。在这 3 个页面中,将生成不同的小部件。其中一个小部件是一个按钮(称为“Next”),它是一个 PageController,但该小部件必须被一个按钮小部件替换,该按钮小部件应该提交(称为“提交”)整个表单(PageView 被包裹在表单)。
看起来很明显,只需编写条件逻辑,将PageView的当前页面与PageView的长度进行比较(PageView填充了List,因此很容易得到长度)。然后在满足正确条件时切换小部件:当当前页面等于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 中填充按钮的更新代码。我将字符串设置为初始值“Next”,然后在 _indexOfCarouselItem + 2 == _triviaDataList.length 为真时更新它。满足条件时,更新的值将是“提交”。
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);
},
);
}