I've built a PageView
and want to control page swiping programmatically using a Bloc
.
I'm using a PageController
and listening for my bloc's ShowPage
state. Then calling pageController.animateTo
to animate the PageView
to the desired page.
The bloc builder builds the PageView.
I suspect the problem I'm having is caused by the BlocBuilder
building a new PageView
on every state change and thus negating the pageController.animateTo
.
My question is firstly ... can the BlockBuilder
be prevented from firing/building for certain states (so it doesn't 'overwrite' my pageController
changes).
or
Is there a better (correct) way of implementing a PageView
with bloc?
I've copied the screen code the basic cubit below for info.
class _TestScreenState extends State<TestScreen> {
final PageController _pageController = PageController(initialPage: 4);
double page = 0;
@override
Widget build(BuildContext context) {
return BlocConsumer<TestCubit, TestState>(listener: (context, state) async {
if (state is DeviceLogsInitial) {
await _animateTo(3);
}
if (state is ShowPage) {
await _animateTo(state.page);
}
}, builder: (context, state) {
// _log.info('Building dialog : page ${_pageController.page}');
return Scaffold(
appBar: AppBar(
title: const Text('Test'),// ${_pageController.page}'),
actions: [
TextButton(
onPressed: () {
page = _nextPage(page);
BlocProvider.of<TestCubit>(context).animate(page);
},
child: const Text('swipe'))
],
),
body: PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
children: const [
Page0(),
Page1(),
Page2(),
Page3(),
],
),
);
});
}
double _nextPage(double page) {
if (page > 3) {
page = 0;
} else {
page = page + 1;
}
return page;
}
Future<void> _animateTo(double _page) async {
_pageController.animateTo(
_page,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
class TestCubit extends Cubit<TestState> {
TestCubit() : super(TestInitial());
Future<void> animate(double page) async {
emit(ShowPage(page));
}
}