具有 Refresh 和 LoadMore 功能的列表并删除旧的

Dom*_*ník 7 flutter flutter-listview

我正在尝试构建列表,您可以在其中添加有限的项目(因此两侧不是无限的)。在顶部,您将进行刷新,它将加载新项目,但您将停留在同一位置(新项目位于您当前位置的顶部)。在底部你会加载更多但相同的,留在同一个地方。我尝试过使用 CustomScrollView 和两个带中心的条子来执行此操作,但我想做的是在刷新时我想删除一些旧项目,发生的情况是它跳转到新的中心并刷新卡片。就是上面那个点。

当前状态

CustomScrollView(
                physics: const BouncingScrollPhysics(
                  parent: AlwaysScrollableScrollPhysics(),
                ),
                center: _mainListKey,
                controller: scrollController,
                cacheExtent: 1000,
                slivers: <Widget>[
                  SliverList(
                      delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) {
                     return ComplexWidget(item: topItems[index]),
                  },
                  childCount: topItems.count,
                  ),),
                   SliverList(
                      key:  _mainListKey
                      delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) {
                     return ComplexWidget(item: bottomItems[index]),
                  },
                  childCount: bottomItems.count,
                  ),),
                ]
              ),
Run Code Online (Sandbox Code Playgroud)

更好的行为描述:

好吧,想象一下 Twitter 应用程序中的相同列表。如果你向下滚动,它将加载越来越多、越来越旧的推文。有时,它会加载后台较新的项目,这些项目会加载到顶部,而不会让您滚动。最后,您可以转到顶部并拉动刷新,它将下载新项目(Twitter 中存在差异),并将项目添加到您的位置之上。

所以有3个触发器:

  1. 向下滚动以加载更多指示器
  2. 拉动刷新
  3. 后台自动刷新

其中任何人都不应该让你改变立场

Dom*_*ník 1

我已经设法 fork oscrollable_positioned_list 到,不需要跳过 itemScrollControlled 。

我已向scrollable_positioned_list添加了两个参数

  final bool keepPosition;
  final String Function(int index)? onItemKey;
Run Code Online (Sandbox Code Playgroud)

在构建时我添加了

    if (widget.itemCount > 0 && widget.onItemKey != null) {
      _lastTargetKey = widget.onItemKey!(primary.target);
    } else {
      _lastTargetKey = null;
    }
Run Code Online (Sandbox Code Playgroud)

额外搜索索引

  String? _lastTargetKey;
  int? _getIndexOfKey() {
    if (widget.onItemKey != null) {
      int? index;
      for (var i = 0; i < widget.itemCount; i++) {
        if (widget.onItemKey!(i) == _lastTargetKey) {
          index = i;
          break;
        }
      }
      return index;
    }
  }
Run Code Online (Sandbox Code Playgroud)

并添加到didUpdateWidget

    if (widget.keepPosition) {
      if (_lastTargetKey != null) {
        var foundIndex = _getIndexOfKey();
        if (foundIndex != null && foundIndex > primary.target) {
          primary.target = foundIndex;
        }
      }
    }
Run Code Online (Sandbox Code Playgroud)