再次构建后,ListVIew 不会滚动到正确的偏移位置

nic*_*tdr 1 flutter

我希望列表视图以偏移量开始。我试图通过在 ListView 中使用以下代码来实现。

控制器:ScrollController(initialScrollOffset:30 * ITEM_HEIGHT),

最初在第一次加载时,列表以正确的偏移量加载。

当通过从父小部件调用 set state 再次构建列表时,列表会更新,但滚动偏移的行为很奇怪。

有两种情况:

  1. 我不滚动列表:在此之后,如果设置状态被称为一切正常。列表得到更新并始终处于正确的偏移量。
  2. 我滚动列表:如果我滚动列表然后重建列表,则滚动偏移量会减少一些项目。列表得到更新,这很好。

是因为当我滚动时它会保留最后一个滚动位置并抵消我的计算吗?我认为这不应该发生,因为它是一个无状态小部件。

class DaysManager extends StatelessWidget {
  final int daysBeforeFocusDate = 30;
  final int totalDaysToInit = 61;
  static final double ITEM_HEIGHT = 108.00;

  ScrollController scrollController;

  List<Day> days;

  DaysManager({DateTime focusDate}) {
      final DateTime startDate =
      focusDate.subtract(Duration(days: daysBeforeFocusDate));
      days = List.generate(totalDaysToInit, (int index) {
      return Day(
       date: startDate.add(
        Duration(days: index),
    ),
  );
});

scrollController = ScrollController(initialScrollOffset: 30 *ITEM_HEIGHT);
}

  @override
  Widget build(BuildContext context) {
   return _buildScrollView();
  }

  ListView _buildScrollView() {
    ListView listView = ListView.builder(
    cacheExtent: 0,
    controller: scrollController,
    itemCount: days.length,
    itemBuilder: (BuildContext context, int index) {
      return days[index];
     });

    return listView;
  }
 }
Run Code Online (Sandbox Code Playgroud)

Wil*_*uce 7

我联系了 Flutter Slack 社区并得到了一个有效的答案。都归功于那边的娄手。这是那次谈话的副本。

ScrollController将它的滚动位置保存PageStorage它所附加到列表的记录中……而不是它自己的 PageStorage。因此,当重新创建小部件时,由于您没有key为 listview 小部件指定新的小部件,它会重用相同的键(颤振内部的众多优化之一以提高性能)。您可以通过添加两行来解决此问题:

import 'dart:math';
...
ListView listView = ListView.builder(
  key: ValueKey<int>(Random(DateTime.now().millisecondsSinceEpoch).nextInt(4294967296)),
...
Run Code Online (Sandbox Code Playgroud)

key每次重新创建列表视图时,您都需要给它一个新的随机PageStorage值,这样它就不会加载它的值。

这是DaysManager您的示例代码中完整的更新代码:

class DaysManager extends StatelessWidget {
  final int daysBeforeFocusDate = 30;
  final int totalDaysToInit = 61;
  static final double ITEM_HEIGHT = 108.00;

  ScrollController scrollController;

  List<Day> days;

  DaysManager({
    DateTime focusDate,
  }) {
    final DateTime startDate = focusDate.subtract(Duration(days: daysBeforeFocusDate));
    days = List.generate(totalDaysToInit, (int index) {
      return Day(
        date: startDate.add(
          Duration(days: index),
        ),
      );
    });

    scrollController = ScrollController(
      initialScrollOffset: 30 *ITEM_HEIGHT,
    );
  }

  @override
  Widget build(BuildContext context) {
    return _buildScrollView();
  }

  ListView _buildScrollView() {
    ListView listView = ListView.builder(
      key: ValueKey<int>(Random(DateTime.now().millisecondsSinceEpoch).nextInt(4294967296)),
      cacheExtent: 0,
      controller: scrollController,
      itemCount: days.length,
      itemBuilder: (BuildContext context, int index) {
        return days[index];
      });

    return listView;
  }
}
Run Code Online (Sandbox Code Playgroud)