Above the first Page that shows, I show a message that the user can swipe left to go to the next page. In onPageChanged I set a bool to dismiss the message and call setState. When I swipe to page 1, at the moment setState is called, the page resets to page 0.
When I remove the conditional text, the page swipes normally.
DartPad gist: https://dartpad.dev/?id=e30a98e4bc531d9cdc93780b6e47f972
Is this a bug or do I miss something?
Full example code below:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
runApp(PageViewTestScreen());
}
class PageViewTestScreen extends StatefulWidget {
PageViewTestScreen({super.key});
@override
State<PageViewTestScreen> createState() => _PageViewTestScreenState();
}
class _PageViewTestScreenState extends State<PageViewTestScreen> {
PageController pageController = PageController(initialPage: 0);
bool lastPage = false;
bool userHasSlided = false;
int numberOfPages = 5;
@override
void initState() {
super.initState();
}
void onPageChanged(int index) {
userHasSlided = true;
lastPage = index == levensgebieden.length-1;
setState(() {});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: lastPage
? FloatingActionButton(
onPressed: () {},
child: Icon(Icons.check),
)
: null,
appBar: AppBar(
foregroundColor: Colors.white,
title: const Text("PageView bug?"),
),
body: ListView(
children: [
const Text("Here are some pages"),
const SizedBox(height: 6),
if (!userHasSlided) const Text("Swipe left to continue."),
SizedBox(
height: 500,
child: PageView(
scrollBehavior: const ScrollBehavior().copyWith(dragDevices: {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
PointerDeviceKind.stylus,
}),
controller: pageController,
onPageChanged: (int index) {
onPageChanged(index);
},
children: [
for (int i = 0; i < 5; i++) card(i),
],
),
)
],
),
),
);
}
Widget card(int index) {
return Card(
child: SizedBox(
height: 500, width: 200, child: Center(child: Text("Page: $index"))),
);
}
}
For cases like this, providing key
helps the element tree .
SizedBox(
key: const Key("my_pageView"),
height: 500,
child: PageView(
More about Keys.