#flutter #mobile #bloc #flutter-pageview #cubit
#flutter #Мобильный #блок #flutter-просмотр страницы #cubit
Вопрос:
Я создал экран каркаса с просмотром страницы в теле и нижней панелью навигации.
Я также создал диспетчер состояний Cubit для этой страницы.
При первом открытии экрана я хочу, чтобы был запущен вызов API. Я также хочу, чтобы была выбрана вкладка 1 (как на просмотре страницы, так и на нижней панели навигации). Когда API возвращает ответ, я хочу, чтобы прослушиватель событий обновил экран и выбрал вкладку 0.
Это хорошо работает для нижней панели навигации, но у меня возникают проблемы с обновлением моего просмотра страницы. Вот мой код:
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _page = 1;
PageController _c;
double iconSize = 32;
bool forceCourseEnrolment = true;
@override
void initState() {
_c = new PageController(
initialPage: 1,
keepPage: false,
);
super.initState();
}
@override
Widget build(BuildContext context) {
return BlocConsumer<HomeScreenCubit, HomeScreenState>(
listener: (context, state) {
debugPrint("listener received something");
if (state is DataRetrieved) {
state.enrolledCourses.length > 0
? forceCourseEnrolment = false
: forceCourseEnrolment = true;
state.enrolledCourses.length > 0 ? _page = 0 : _page = 1;
var hasClients = this._c.hasClients;
debugPrint("this._c.hasClients $hasClients");
// This prints: this._c.hasClients false
// Enabling this line:
// this._c.jumpToPage(_page);
// leads to:
// [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: 'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 112 pos 12: '_positions.isNotEmpty': ScrollController not attached to any scroll views.
}
}, builder: (context, state) {
if (state is HomeScreenInitial) {
context.bloc<HomeScreenCubit>().retrieveData();
return Scaffold(
body: SpinKitChasingDots(
color: COLOR_main_purple,
size: 50.0,
));
}
return Scaffold(
body: PageView(
controller: _c,
onPageChanged: (newPage) {
setState(() {
this._page = newPage;
});
},
physics: NeverScrollableScrollPhysics(),
children: [
PurchasedCoursesTab(),
ElearningTab(),
MyPracticeTab(),
ProfileTab(),
],
),
bottomNavigationBar: SizedBox(
height: 80,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(30),
topLeft: Radius.circular(30)),
boxShadow: [
BoxShadow(
color: Colors.black38.withOpacity(0.1),
spreadRadius: 0,
blurRadius: 25),
],
),
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
child: BottomNavigationBar(
currentIndex: _page,
onTap: (index) {
if (forceCourseEnrolment == false) {
this._c.animateToPage(index,
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut);
}
},
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.white,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
// title: Text(""),
title: showIndicator(_page == 0),
icon: Container(
width: iconSize,
height: iconSize,
child: SvgPicture.asset('assets/images/ic_run.svg',
color: _page == 0
? COLOR_main_purple
: forceCourseEnrolment == false
? Colors.black
: COLOR_main_text_grey_with_opacity),
)),
BottomNavigationBarItem(
title: showIndicator(_page == 1),
icon: Container(
width: iconSize,
height: iconSize,
child: SvgPicture.asset(
'assets/images/ic_e_learning.svg',
color: _page == 1
? COLOR_main_purple
: Colors.black),
)),
BottomNavigationBarItem(
title: showIndicator(_page == 2),
icon: Container(
width: iconSize,
height: iconSize,
child: SvgPicture.asset(
'assets/images/ic_journal.svg',
color: _page == 2
? COLOR_main_purple
: forceCourseEnrolment == false
? Colors.black
: COLOR_main_text_grey_with_opacity),
)),
BottomNavigationBarItem(
title: showIndicator(_page == 3),
// title: Text(_page == 3 ? "•" : "", style: TextStyle(
// color: COLOR_main_purple, fontSize: 24.0)),
icon: Container(
width: iconSize,
height: iconSize,
child: SvgPicture.asset(
'assets/images/ic_gamification.svg',
color: _page == 3
? COLOR_main_purple
: forceCourseEnrolment == false
? Colors.black
: COLOR_main_text_grey_with_opacity),
)),
],
),
)),
));
});
}
}
Ошибка, с которой я сталкиваюсь, когда пытаюсь сменить страницу в прослушивателе BlocConsumer:
[ОШИБКА: flutter /lib /ui/ui_dart_state.cc(177)] Необработанное исключение: ‘пакет: flutter /src / widgets/scroll_controller.dart’: Ошибка утверждения: строка 112 поз 12: ‘_positions.isNotEmpty’: ScrollController не привязан ни к одному виду прокрутки.
Ответ №1:
Обнаружил, что я могу заставить это работать, добавив к слушателю следующее:
if (state is DataRetrieved) {
state.enrolledCourses.length > 0
? forceCourseEnrolment = false
: forceCourseEnrolment = true;
state.enrolledCourses.length > 0 ? _page = 0 : _page = 1;
Future.delayed(Duration(milliseconds: 50), () {
if (this._c.hasClients) {
this._c.jumpToPage(_page);
}
});
}
Я нахожу это уродливым решением, поэтому не буду отмечать это как ответ. Пожалуйста, дайте мне знать, если вы знаете лучший способ справиться с этим.
Ответ №2:
Вы можете попробовать удалить этот код? Если вам нужно показать загрузку, вы можете попробовать добавить ее в PurchasedCoursesTab.
if (state is HomeScreenInitial) {
context.bloc<HomeScreenCubit>().retrieveData();
return Scaffold(
body: SpinKitChasingDots(
color: COLOR_main_purple,
size: 50.0,
));
}
Эта проблема возникает из-за того, что на этот раз ваш PageController
файл не привязан к просмотру страницы.