【问题标题】:Flutter - PageView animatedToPage will load middle page. How to avoid it?Flutter - PageView animatedToPage 将加载中间页面。如何避免?
【发布时间】:2019-08-21 07:59:32
【问题描述】:

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

  1. 使用animateToPage
  2. 使用jumpToPage

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

如何避免?

【问题讨论】:

  • 假设你在0th页面,你需要动画到9th页面,你可以在这里做的是,使用jumpToPage(8),然后使用animateToPage(9)

标签: flutter


【解决方案1】:

我们可以做到这一点

  1. 将 lastPage 小部件交换到当前页面的下一个位置
  2. 动画到下一页
  3. 跳转到真正的最后一页索引
  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
}

详细的外观

// 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();
  });
}

完整的工作示例存储库

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

【讨论】:

  • 聪明的解决方案,它看起来真的很棒,但是我的第一个抱怨是小部件将被多次渲染。至少对我来说这并不理想,因为我在 initState() 中拨打电话
  • 这应该是 Flutter 的功能吗?我们不喜欢使用 `WidgetsBinding.instance.addPostFrameCallback()` 来刷新小部件。
猜你喜欢
  • 2020-09-03
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 2020-03-16
  • 2020-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多