Как мне сбросить настройки контроллера, когда я вернусь или закончу?
У меня класс QuestionController расширяется
GetxController
Когда я выхожу со страницы с помощью элементов управления, я хочу, чтобы она перестала работать (потому что она все еще работает в фоновом режиме) и запустилась снова, если я вернусь на эту страницу.
Я пробовал: я добавил их после маршрута
ScoreScreen()
(в
nextQuestion ()
):
_isAnswered = false;
_questionNumber.value = 1;
Я сбрасываю значения перед тем, как перейти на страницу результатов. Это может сработать, если вы перейдете на страницу результатов, но если вы вернетесь раньше, этого не произойдет. (верхний вопрос № / 4 здесь не работает). Так что этот способ не подходит.
Как я могу остановить и сбросить его, когда страница закрывается?
Код класса контроллера:
class QuestionController extends GetxController
with SingleGetTickerProviderMixin {
PageController _pageController;
PageController get pageController => this._pageController;
List<Question> _questions = questions_data
.map(
(e) => Question(
id: e["id"],
question: e["question"],
options: e["options"],
answer: e["answer_index"]),
)
.toList();
List<Question> get questions => this._questions;
bool _isAnswered = false;
bool get isAnswered => this._isAnswered;
int _correctAns;
int get correctAns => this._correctAns;
int _selectedAns;
int get selectedAns => this._selectedAns;
RxInt _questionNumber = 1.obs;
RxInt get questionNumber => this._questionNumber;
int _numOfCorrectAns = 0;
int get numOfCorrectAns => this._numOfCorrectAns;
@override
void onInit() {
_pageController = PageController();
super.onInit();
}
@override
void onClose() {
super.onClose();
_pageController.dispose();
}
void checkAns(Question question, int selectedIndex) {
_isAnswered = true;
_correctAns = question.answer;
_selectedAns = selectedIndex;
if (_correctAns == _selectedAns) _numOfCorrectAns++;
update();
Future.delayed(Duration(seconds: 2), () {
nextQuestion();
});
}
void nextQuestion() {
if (_questionNumber.value != _questions.length) {
_isAnswered = false;
_pageController.nextPage(
duration: Duration(milliseconds: 300), curve: Curves.ease);
} else {
Get.off(ScoreScreen(correctNum: _numOfCorrectAns)); // GetMaterialApp()
// _isAnswered = false;
_numOfCorrectAns = 0;
//_questionNumber.value = 1;
}
}
void updateTheQuestionNum(int index) {
_questionNumber.value = index + 1;
}
}
Полный код ниже
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:get/get.dart'; // get: ^3.25.4
// QuizPage() ===============> 50. line (Question 1/4) 81. line
// QuestionCard() ==============> 116. line
// Option() ===================> 163. line
// QuestionController() ========> 218. line
// ScoreScreen() ================> 345. line
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(canvasColor: Colors.blue),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Home Page"),
),
body: Center(
child: InkWell(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => QuizPage()));
},
child: Container(
padding: EdgeInsets.all(22),
color: Colors.green,
child: Text(
"Go Quiz Page",
style: TextStyle(color: Colors.white),
),
),
),
),
);
}
}
class QuizPage extends StatelessWidget {
const QuizPage({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
QuestionController _questionController = Get.put(QuestionController());
return Scaffold(
appBar: AppBar(
title: Text("Quiz Page"),
),
body: Stack(
children: [
SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 16,
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Obx(
() => Center(
child: RichText(
text: TextSpan(
// text,style default adjust here OR:children[TextSpan(1,adjust 1),TextSpan(2,adjust 2),..]
text:
"Question ${_questionController._questionNumber.value}",
style: TextStyle(
fontSize: 33, color: Colors.white70),
children: [
TextSpan(
text:
"/${_questionController._questions.length}",
style: TextStyle(fontSize: 25))
])),
),
),
),
Divider(color: Colors.white70, thickness: 1),
SizedBox(
height: 16,
),
Expanded(
child: PageView.builder(
physics: NeverScrollableScrollPhysics(),
controller: _questionController._pageController,
onPageChanged: _questionController.updateTheQuestionNum,
itemCount: _questionController.questions.length,
itemBuilder: (context, index) => QuestionCard(
question: _questionController.questions[index],
),
),
)
],
),
)
],
),
);
}
}
class QuestionCard extends StatelessWidget {
final Question question;
const QuestionCard({
Key key,
@required this.question,
}) : super(key: key);
@override
Widget build(BuildContext context) {
QuestionController _controller = Get.put(QuestionController());
return Container(
margin: EdgeInsets.only(left: 16, right: 16, bottom: 16),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.white,
),
child: Column(
children: [
Text(
question.question,
style: TextStyle(fontSize: 22),
),
SizedBox(
height: 8,
),
Flexible(
child: SingleChildScrollView(
child: Column(
children: [
...List.generate(
question.options.length,
(index) => Option(
text: question.options[index],
index: index,
press: () => _controller.checkAns(question, index)))
],
),
),
)
],
),
);
}
}
class Option extends StatelessWidget {
final String text;
final int index;
final VoidCallback press;
const Option({
Key key,
@required this.text,
@required this.index,
@required this.press,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<QuestionController>(
init: QuestionController(),
builder: (q) {
Color getRightColor() {
if (q.isAnswered) {
if (index == q._correctAns) {
return Colors.green;
} else if (index == q.selectedAns &&
q.selectedAns != q.correctAns) {
return Colors.red;
}
}
return Colors.blue;
}
return InkWell(
onTap: press,
child: Container(
//-- Option
margin: EdgeInsets.only(top: 16),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: getRightColor(),
borderRadius: BorderRadius.circular(16)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${index + 1}. $text",
style: TextStyle(fontSize: 16, color: Colors.white),
),
],
),
),
);
});
}
}
class QuestionController extends GetxController
with SingleGetTickerProviderMixin {
PageController _pageController;
PageController get pageController => this._pageController;
List<Question> _questions = questions_data
.map(
(e) => Question(
id: e["id"],
question: e["question"],
options: e["options"],
answer: e["answer_index"]),
)
.toList();
List<Question> get questions => this._questions;
bool _isAnswered = false;
bool get isAnswered => this._isAnswered;
int _correctAns;
int get correctAns => this._correctAns;
int _selectedAns;
int get selectedAns => this._selectedAns;
RxInt _questionNumber = 1.obs;
RxInt get questionNumber => this._questionNumber;
int _numOfCorrectAns = 0;
int get numOfCorrectAns => this._numOfCorrectAns;
@override
void onInit() {
_pageController = PageController();
//_pageController.addListener(() { _questionNumber.value = _pageController.page.round()+1; });
super.onInit();
}
@override
void onClose() {
super.onClose();
_pageController.dispose();
}
void checkAns(Question question, int selectedIndex) {
_isAnswered = true;
_correctAns = question.answer;
_selectedAns = selectedIndex;
if (_correctAns == _selectedAns) _numOfCorrectAns++;
update();
Future.delayed(Duration(seconds: 2), () {
nextQuestion();
});
}
void nextQuestion() {
if (_questionNumber.value != _questions.length) {
_isAnswered = false;
_pageController.nextPage(
duration: Duration(milliseconds: 300), curve: Curves.ease);
} else {
Get.off(ScoreScreen(correctNum: _numOfCorrectAns)); // GetMaterialApp()
// _isAnswered = false;
_numOfCorrectAns = 0;
//_questionNumber.value = 1;
}
}
void updateTheQuestionNum(int index) {
_questionNumber.value = index + 1;
}
}
class Question {
final int id, answer;
final String question;
final List<String> options;
Question({
@required this.id,
@required this.question,
@required this.options,
@required this.answer,
});
}
const List questions_data = [
{
"id": 1,
"question": "Question 1",
"options": ['option A', 'B', 'C', 'D'],
"answer_index": 3,
},
{
"id": 2,
"question": "Question 2",
"options": ['option A', 'B', 'C', 'D'],
"answer_index": 2,
},
{
"id": 3,
"question": "Question 3",
"options": ['option A', 'B', 'C', 'D'],
"answer_index": 0,
},
{
"id": 4,
"question": "Question 4",
"options": ['option A', 'B', 'C', 'D'],
"answer_index": 0,
},
];
class ScoreScreen extends StatelessWidget {
final int correctNum;
ScoreScreen({@required this.correctNum});
@override
Widget build(BuildContext context) {
QuestionController _qController = Get.put(QuestionController());
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
Column(
children: [
Spacer(
flex: 2,
),
Text(
"Score",
style: TextStyle(fontSize: 55, color: Colors.white),
),
Spacer(),
Text(
"${correctNum * 10}/${_qController.questions.length * 10}",
style: TextStyle(fontSize: 33, color: Colors.white),
),
Spacer(
flex: 2,
),
InkWell(
onTap: () => Get.back(),
borderRadius: BorderRadius.circular(16),
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white24),
child: Text(
"Back to Home Page",
style: TextStyle(color: Colors.white),
),
),
),
Spacer(),
],
),
],
),
);
}
}
7 ответов
Обновленный ответ:
Хорошо, после просмотра вашего полного кода для моего решения требуется пара дополнительных шагов.
Добавьте это в свой класс контроллера. Его нужно вызвать в onPressed из вашего
void resetQuestionNumber() => _questionNumber.value = 1;
Вам нужно будет инициализировать контроллер раньше, чтобы вы могли добавить его в свой
final _questionController = Get.put(QuestionController());
В
onTap
вашей
HomeScreen
теперь выглядит так.
onTap: () {
_questionController.resetQuestionNumber();
Navigator.push(
context, MaterialPageRoute(builder: (context) => QuizPage()));
},
Это должно сработать. Индекс не обновлялся до тех пор, пока вам не ответили на вопрос, поэтому просто нужно сбросить
_questionNumber
перед поездкой в
QuizPage
и после этого догоняет. Ваш
updateTheQuestionNum
может уйти полностью, и вам не нужно ничего обрабатывать в
onPageChanged
из
PageView.builder
больше.
Оригинальный ответ:
Если ты просто хочешь этого
RxInt _questionNumber
чтобы соответствовать значению
_pageController
вы можете добавить слушателя в свой
onInit
_pageController.addListener(() {
_questionNumber.value = _pageController.page.round() + 1;
});
Изменить: добавлен + 1 для учета индекса, начиная с 0
Если вы хотите сбросить только один контроллер, вы можете использовать
Get.delete<ExecutableController>();
для сброса всех контроллеров
Get.deleteAll();
вы можете прослушать "onBack event" и избавиться от контроллера, вот пример
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
disposeController(context);
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
_moveToSignInScreen(context);
}),
title: Text("Profile"),
),
),
);
}
void disposeController(BuildContext context){
//or what you wnat to dispose/clear
_pageController.dispose()
}
InkWell(
onTap: () {
/*add QuestionController().refresh();*/
QuestionController().refresh();
Get.back();
},
borderRadius: BorderRadius.circular(16),
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white24),
),
child: Text(
Back to Home Page",
style: TextStyle(color: Colors.white),
),
),
),
Автоматически:
Get.to(() => DashboardPage(), binding: BindingsBuilder.put(() => DashboardController()));
Вручную:
Вы можете удалить контроллер на задней кнопке, а затем снова установить его, это даст тот же результат, что и сброс контроллера:
удалите это:
Получить.удалить();
Добавьте еще раз:
Get.put(Панель управления());
Вы можете использовать Get.reset(), если у вас только один контроллер, он очищает все зарегистрированные экземпляры.
Используйте initState для решения этой проблемы
В initState вызовите setState, а затем измените значение контроллера на 0 ....
Удачи 😇😇😇...