问题描述
老师您好, 我在使用 PageView.builder
指定 itemCount
后, 在后续的新增数据并跳转至最新页时onPageChanged
监听返回的page数据不正确, 这是属于flutter的bug还是我操作的不正确, 望老师指正.
问题代码
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: const MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController controller = PageController(initialPage: 0);
List data = ["1", "1", "1",];
int correctPage = 0;
void initState() {
super.initState();
}
Widget itemBuilder(BuildContext ctx, int page) {
return Container(
height: 100,
child: Center(
child: Text(page.toString()),
),
);
}
onPageChanged(int page){
//这里返回的 page 不正确
//flutter: correctPage: 8, onPageChanged: 2
print("correctPage: ${correctPage}, onPageChanged: ${page}");
}
Widget build(BuildContext context) {
return Container(
child: Column(children: [
Container(
height: 100,
child: PageView.builder(
itemBuilder: itemBuilder,
itemCount: data.length,
controller: controller,
onPageChanged: onPageChanged,
),
),
ElevatedButton(
onPressed: () {
setState((){
data.addAll(["1", "1", "1", "1", "1", "1"]);
if (controller.hasClients) {
correctPage = data.length - 1;
controller.jumpToPage(correctPage);
//controller.position.;
}
});
},
child: Text("push data"),
)
]),
);
}
}
源码探讨
// pageview - 950行
if (notification.depth == 0 && widget.onPageChanged != null && notification is ScrollUpdateNotification) {
final PageMetrics metrics = notification.metrics as PageMetrics;
final int currentPage = metrics.page!.round();
if (currentPage != _lastReportedPage) {
_lastReportedPage = currentPage;
widget.onPageChanged!(currentPage);
}
}
metrics.page
/// The current page displayed in the [PageView].
double? get page {
return math.max(0.0, pixels.clamp(minScrollExtent, maxScrollExtent)) /
math.max(1.0, viewportDimension * viewportFraction);
}
从代码可以发现 maxScrollExtent
限制了 page 的获取, 一种思路是 复制一份pageview源码将 clamp
方法的限制去掉, 但我不清楚这是否是一种正确的操作
解锁Flutter开发新姿势,,系统掌握Flutter开发核心技术。
了解课程