在很长的 ListView 中记住滚动位置

Posted

技术标签:

【中文标题】在很长的 ListView 中记住滚动位置【英文标题】:Remember Scroll Position in very long ListView 【发布时间】:2020-10-19 11:32:57 【问题描述】:

我的 Flutter 应用程序中显示了很长的项目列表,该列表由 API 填充,用户可以选择刷新列表以获取最新信息。

有什么方法可以知道用户在任何特定时间滚动到列表中的哪个位置?

然后当用户按下刷新时,我可以滚动回他们正在查看的列表中的最新位置?

我确实使用了这个“滚动位置列表”,但是当我滚动时,帧速率下降了很多......下降到 20 fps,如果可能的话,我想要一个平滑的 60 fps。 https://pub.flutter-io.cn/packages/scrollable_positioned_list

【问题讨论】:

更新,我已经设法通过优化列表本身的小部件来提高帧速率。看起来我可以从 scrollable_positioned_list 获得良好的性能,并且仍然能够使用它添加到 ListView.builder() 的额外功能 【参考方案1】:

您是否尝试过使用 --release 运行您的应用程序?发布模式比调试模式具有更好的性能。而且我认为您可以使用普通的ListView.builder()ScrollController https://api.flutter.dev/flutter/widgets/ScrollController-class.html 可能比pub.dev 上的可滚动列表具有更好的性能

【讨论】:

感谢您的评论,请参阅上面的评论。 ListView.builder() 不会让我可靠地知道顶部行中的数据是什么,这比物理滚动位置更需要。 你不能只使用列表来查看元素的顺序吗?【参考方案2】:

我不知道 scrollable_positioned_list 包本身,但我认为您的实现不需要它。

首先,对于长列表,出于性能原因使用ListView.builder() 很重要。这只会加载当前在屏幕上可见的项目。这样可以节省很多资源(相当于android中的RecyclerView)。

要获取列表的位置,可以保存列表的滚动偏移值。您可以通过ScrollController 获取此信息。

这是我的示例代码:

import 'package:flutter/material.dart';
import 'package:preferences/preference_service.dart';

class MyListView extends StatefulWidget 
  final String _prefKey = 'listViewOffset';

  @override
  _MyListViewState createState() => _MyListViewState();


class _MyListViewState extends State<MyListView> 
  ScrollController controller;

  @override
  void initState() 
    controller = ScrollController(initialScrollOffset: PrefService.getDouble(widget.prefKey);
    controller.addListener(() 
      PrefService.setDouble(widget.prefKey, controller.offset);
    );
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    throw ListView.builder(
      controller: controller,
      itemBuilder: (BuildContext context, int position) 
        return ListTile(title: Text("Position $position"));
      
    );
  

  @override
  void dispose() 
    controller.dispose(); // remove the listeners of our controller
    super.dispose();
  

为了保存偏移量,我使用包preferences,但您也可以使用shared_preferences 包。

很遗憾,我没有机会在已完成的应用程序中测试我的代码,但我希望它能做到应有的效果。

【讨论】:

感谢您的评论。此选项在我的情况下实际上不起作用,因为我想知道数据列表中的哪个元素位于顶部。如果所有行的高度都相同,那么这会起作用,但我不能总是保证这一点。每次刷新时,项目的数量可能会发生变化,因此我需要的不是物理位置,而是行中的数据。

以上是关于在很长的 ListView 中记住滚动位置的主要内容,如果未能解决你的问题,请参考以下文章

返回ListView时保持/保存/恢复滚动位置

如何使用 Pytorch 中的截断反向传播(闪电)在很长的序列上运行 LSTM?

MacOS 如何选择鼠标不飘滚动平滑

c#listview的标题怎么禁止拖拽更换位置

平均一个很长的列表[双]而不在 Scala 中获得无穷大

基于不同滚动位置的动画标题