请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于 PageView.builder onPageChanged 监听返回的数据不正确,该如何正确解决

问题描述

老师您好, 我在使用 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方法的限制去掉, 但我不清楚这是否是一种正确的操作

正在回答 回答被采纳积分+3

1回答

CrazyCodeBoy 2022-07-18 00:39:37
问题应该在于你中间修改过数控,导致pagechanged回调和真是数据对不上。
可以用你说的将方法限制去掉然后运行下看是否能满足你的需求,同时需要留一下是否会有别的问题。
0 回复 有任何疑惑可以回复我~
  • 提问者 慕圣2430575 #1
    按照老师说的, 那我调整为最后修改数值, 但是 `第一次`输出的page还是不行, 老师可还有其他方法? , 麻烦老师跑下我的代码.
    
    **修改代码**
    ```dart
    if (controller.hasClients) {
        var widgetsBinding=WidgetsBinding.instance;
        widgetsBinding.addPostFrameCallback((){
            correctPage = data.length - 1;
            controller.jumpToPage(correctPage);
        });
    }
    ```
    
    **运行结果**
    ```
    flutter: build
    flutter: correctPage: 8, onPageChanged: 2
    flutter: build
    flutter: correctPage: 14, onPageChanged: 14
    flutter: build
    flutter: correctPage: 20, onPageChanged: 20
    ```
    回复 有任何疑惑可以回复我~ 2022-07-19 05:59:28
  • CrazyCodeBoy 回复 提问者 慕圣2430575 #2
    你试试中间不修改data,看能否获取到正确的page呢
    回复 有任何疑惑可以回复我~ 2022-07-20 08:52:35
  • 提问者 慕圣2430575 回复 CrazyCodeBoy #3
    不修改肯定是没问题的 相当于直接 jumptopage, 并且正常滚动所触发的 onpagechanged 也是正确的
    回复 有任何疑惑可以回复我~ 2022-07-20 08:58:24
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信