在显示的第一页上方,我显示一条消息,用户可以向左滑动以转到下一页。在 onPageChanged 中,我设置了一个布尔值来关闭消息并调用 setState。当我滑动到第 1 页时,在调用 setState 的那一刻,页面重置为第 0 页。
当我删除条件文本时,页面会正常滑动。
DartPad 要点:https://dartpad.dev/?id=e30a98e4bc531d9cdc93780b6e47f972
这是一个错误还是我错过了什么?
完整示例代码如下:
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"))),
);
}
}
这是预期的,因为当
userHasSlided
发生变化时,该 ListView
的子级也发生了变化,这会触发小部件重建。由于 PageView
不是常数,因此它也会被重建。重建会中断用户的滑动进度,从而将页面重置为 0。
您可以尝试在其他地方(
ListView
之外)添加条件情况,也许在AppBar
中,并删除ListView
中的条件文本,您会注意到PageView
将按预期工作。这是因为ListView
没有被重建。