【问题标题】:flutter ListView scroll to index not available颤动 ListView 滚动到索引不可用
【发布时间】:2019-05-31 01:39:56
【问题描述】:

我需要什么:

我想按某个索引滚动列表,我该怎么做。

我所知道的:

scrollToIndex 应该从第 n 个索引开始,但是我们如何滚动到任何索引?

【问题讨论】:

标签: dart flutter


【解决方案1】:

不幸的是,ListView 没有内置的 scrollToIndex() 函数方法。您必须开发自己的方法来测量该元素对 animateTo()jumpTo() 的偏移量,或者您可以搜索这些建议的解决方案/插件或从其他帖子中搜索,例如 Flutter: Scrolling to a widget in ListView

(自 2017 年以来,flutter/issues/12319 讨论了一般的 scrollToIndex 问题,但目前还没有计划)


但是有一种不同类型的 ListView 确实支持 scrollToIndex(Slashbin 提到过):

您的设置与 ListView 完全一样,并且工作方式相同,只是您现在可以访问 ItemScrollController

  • jumpTo({index, alignment})
  • scrollTo({index, alignment, duration, curve})

简化示例:

ItemScrollController _scrollController = ItemScrollController();

ScrollablePositionedList.builder(
  itemScrollController: _scrollController,
  itemCount: _myList.length,
  itemBuilder: (context, index) {
    return _myList[index];
  },
)

_scrollController.scrollTo(index: 150, duration: Duration(seconds: 1));

(请注意,此库由 Google 开发,而非 Flutter 核心团队开发。)

【讨论】:

  • 很棒的答案。虽然我注意到当index == item.length - 1 时,scrollController 的行为很有趣。可能是因为我用了BouncingScrollPhysics()
  • ScrollablePositionedList 的缺点是它与增量滚动要求不兼容(例如响应向上/向下箭头键),因为它的 API 确实涉及偏移量(甚至是相对偏移量)。
  • 但是我不能为ScrollablePositionedList设置控制器键,如果你想做更多的事情就不好了
【解决方案2】:

ScrollablePositionedList 可以用于此。 https://github.com/google/flutter.widgets/tree/master/packages/scrollable_positioned_list

Pub link - https://pub.dev/packages/scrollable_positioned_list

final ItemScrollController itemScrollController = ItemScrollController();
final ItemPositionsListener itemPositionListener = ItemPositionsListener.create();

ScrollablePositionedList.builder(
  itemCount: 500,
  itemBuilder: (context, index) => Text('Item $index'),
  itemScrollController: itemScrollController,
  itemPositionsListener: itemPositionListener,
);

然后可以通过以下方式滚动到特定项目:

itemScrollController.scrollTo(
  index: 150,
  duration: Duration(seconds: 2),
  curve: Curves.easeInOutCubic);

【讨论】:

    【解决方案3】:

    使用scroll_to_index lib,这里滚动总是执行到第六个位置,如下面的硬编码

    dependencies:
        scroll_to_index: ^1.0.6
    

    代码片段:

    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      final scrollDirection = Axis.vertical;
    
      AutoScrollController controller;
      List<List<int>> randomList;
    
      @override
      void initState() {
        super.initState();
        controller = AutoScrollController(
            viewportBoundaryGetter: () =>
                Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
            axis: scrollDirection);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: ListView(
            scrollDirection: scrollDirection,
            controller: controller,
            children: <Widget>[
              ...List.generate(20, (index) {
                return AutoScrollTag(
                  key: ValueKey(index),
                  controller: controller,
                  index: index,
                  child: Container(
                    height: 100,
                    color: Colors.red,
                    margin: EdgeInsets.all(10),
                    child: Center(child: Text('index: $index')),
                  ),
                  highlightColor: Colors.black.withOpacity(0.1),
                );
              }),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _scrollToIndex,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
      // Scroll listview to the sixth item of list, scrollling is dependent on this number
      Future _scrollToIndex() async {
        await controller.scrollToIndex(6, preferPosition: AutoScrollPosition.begin);
      }
    }
    

    输出:

    【讨论】:

      【解决方案4】:

      如果您知道 listview 项目大小,则滚动到首选索引很简单,例如:

      var index = 15;
      var widthOfItem =
      176; //in dp. width needed for horizontallistView;
      var heightOfItem =
      200; //in dp. height need for vertical listView;
      listViewScrollController.jumpTo(index * widthOfItem.toDouble());
      

      listViewScrollController.animateTo(
      index * widthOfItem.toDouble(),
      duration: Duration(milliseconds: 500),
      curve: Curves.ease);
      

      【讨论】:

        【解决方案5】:

        找到一个 gist,其工作 gist url 是 https://gist.github.com/debuggerx01/b8ef756ee02b3eb82ec3702f14ba94e6

        这个要点正在使用一个计算矩形大小的包。 https://pub.dartlang.org/packages/rect_getter

        【讨论】:

        • 是的,它可以工作,但看起来我的列表视图中带有 cmets 的 FPS 变得非常低.. 操作太多。
        • 如果我使用 ListView.builder 是否可以使用此解决方案?
        猜你喜欢
        • 2021-07-11
        • 2022-11-15
        • 2021-03-15
        • 2020-02-14
        • 1970-01-01
        • 2020-12-20
        • 2021-06-09
        • 2021-04-30
        • 2019-03-03
        相关资源
        最近更新 更多