Flutter - PageView animationToPage 将加载中间页面。如何避免?

Leo*_*o.J 12 flutter

我有一个 PageView,我想以编程方式滚动 pageView,所以我有两个选择:

  1. animateToPage
  2. jumpToPage

现在,我需要平滑的过渡效果,所以我必须使用第一个 api。但是,我有一个问题:animateToPage当我从第一页滚动到最后一页时,将加载此时不需要显示的中间页面。(jumpToPage 没有这个问题,但我需要动画)。

如何避免?

eja*_*abu 11

我们可以通过

  1. 将 lastPage Widget 交换到当前页面的下一个位置
  2. 动画到下一页
  3. 跳转到真正的 lastPage 索引
  4. 将交换的索引刷新为其先前的值

在此示例中,我使用了固定的PageView 子项计数,即 8。

演示

演示

比较

  1. 合并到第 8 页按钮

正如 CopsOnRoad 建议的那样,此按钮将触发滚动动画到最后一页(在本例中为第 8 页)。首先,我们 jumpToPage(6),然后 animateToPage(7, ..)。

此方法有效,但不利的是,用户会注意到当前页面突然更改为第 7 页

  1. Flash 跳转到第 8 页按钮

与第一种方法不同,此按钮将避免不必要地显示第 7 页

语法说明

这是主要功能

void flashToEight() async {
  int pageCurrent = pageController.page.round();
  int pageTarget = 7;
  if (pageCurrent == pageTarget){
    return;
  }
  swapChildren(pageCurrent, pageTarget); // Step # 1
  await quickJump(pageCurrent, pageTarget); // Step # 2 and # 3
  WidgetsBinding.instance.addPostFrameCallback(refreshChildren); // Step # 4
}
Run Code Online (Sandbox Code Playgroud)

细部外观

// Step # 1
void swapChildren(int pageCurrent, int pageTarget) {
  List<Widget> newVisiblePageViews = [];
  newVisiblePageViews.addAll(pageViews);

  if (pageTarget > pageCurrent) {
    newVisiblePageViews[pageCurrent + 1] = visiblePageViews[pageTarget];
  } else if (pageTarget < pageCurrent) {
    newVisiblePageViews[pageCurrent - 1] = visiblePageViews[pageTarget];
  }

  setState(() {
    visiblePageViews = newVisiblePageViews;
  });
}

// Step # 2 and # 3
Future quickJump(int pageCurrent, int pageTarget) async {
  int quickJumpTarget;

  if (pageTarget > pageCurrent) {
    quickJumpTarget = pageCurrent + 1;
  } else if (pageTarget < pageCurrent) {
    quickJumpTarget = pageCurrent - 1;
  }
  await pageController.animateToPage(
    quickJumpTarget,
    curve: Curves.easeIn,
    duration: Duration(seconds: 1),
  );
  pageController.jumpToPage(pageTarget);
}

// Step # 4
List<Widget> createPageContents() {
    return <Widget>[
      PageContent(1),
      PageContent(2),
      PageContent(3),
      PageContent(4),
      PageContent(5),
      PageContent(6),
      PageContent(7),
      PageContent(8),
    ];
  }

void refreshChildren(Duration duration) {
  setState(() {
    visiblePageViews = createPageContents();
  });
}
Run Code Online (Sandbox Code Playgroud)

完整的工作示例存储库

您可以查看完整的源代码并在本地构建。GitHub

  • 聪明的解决方案,它看起来真的很棒,但是我的第一个抱怨是小部件将被渲染多次。至少对于我的情况来说并不理想,因为我在 initState() 中进行调用 (5认同)