当前面临条件逻辑和PageView小部件的问题。假设PageView将动态生成3个页面。在这3页中,将生成不同的窗口小部件。其中一个小部件是一个按钮(称为“ Next”),它是一个PageController,但是该小部件必须替换为一个按钮小部件,该按钮小部件应该提交(称为“ Submit”)整个表单(将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中填充按钮的更新代码。我将String设置为初始值“ Next”,然后在_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);
},
);
}
答案 0 :(得分:1)
我现在正在打电话,所以我不能保证我要发布的验证码是正确的,但是您会明白的。
首先:如果大小相等,我认为您不需要2个按钮,因此您可以执行以下操作:
child: Text( _indexOfCarouselItem += 1 != _triviaDataList.length
? 'Next' : 'Submit')
然后在onPressed中使用相同的逻辑:
onPressed() {
_indexOfCarouselItem += 1 != _triviaDataList.length ? doSomethibg : doSomethingDifferent;
}
编辑: 好吧,如果我现在正确理解的问题是,由于转换,按钮显示“提交”,但是没有问题吗?如果是这种情况,您可以像您所说的那样添加延迟,但是我认为更好的方法是将按钮的文本与问题联系起来。我的意思是您可以保留实际的逻辑(因为它可以工作)并添加如下内容:
子级:Text(_indexOfCarouselItem + = 1!= _triviaDataList.length && questionText!=“” ? '下一步':'提交')
如果... else ...块也可以应用此逻辑。
编辑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";
});
}
},
);
}