搜索插件、代码仓与 APP 分类

flutter_list_view 封面
插件详情v1.1.29

flutter_list_view

提供增强的列表视图,包含跳转索引、保持位置等功能。

AndroidiOSWebmacOSWindowsLinux
近 30 天下载
1.1万
喜欢数
133
Pub 分数
140

安装插件

flutter pub add flutter_list_view

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

一个增强标准 ListView 的 Flutter 包,提供诸如跳转索引导航、重建期间的位置持久化以及改进的滚动行为等高级功能。它旨在通过保持滚动状态并在大型数据集中实现快速导航,为列表密集型应用提供更流畅的用户体验。适用于需要在多个平台上高效且响应迅速地管理列表的应用程序。

适合场景

  • 大型数据列表,快速导航
  • 在更新后保持滚动位置
  • 长列表中的增强用户体验
  • 跨平台列表一致性
  • 动态内容重新加载时保持滚动状态
  • 实现字母跳转索引

主要特点

  • 快速导航的跳转索引
  • 在重建期间保持滚动位置
  • 大型列表的优化性能
  • 支持所有主要的 Flutter 平台
  • 可自定义的索引指示器
  • 平滑滚动过渡

适合对象

  • 开发复杂列表界面的开发者
  • 动态或频繁更新的列表的应用程序
  • 需要直观列表导航的用户
  • 跨平台移动和Web应用
  • 需要高性能列表渲染的应用程序

使用建议

  • 需要与现有列表逻辑仔细集成
  • 可能会略微增加包大小
  • 最适合包含超过50项的列表
  • 对非标准列表布局的自定义有限
  • 依赖稳定的 Flutter 版本兼容性

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

Flutter List View

Enhance list view to support scroll to index, jump to index, header sticky, enable without scroll when insert data on top and turn performance to reused items.

Features

  1. Support the list view to jump to and scroll to index.
  2. Support for inserting data without scrolling
  3. Support for show top in reverse mode if the data can't fill the full viewport.
  4. Support sticky header.
  5. Support integrated pull_to_refresh
  6. When initializing data, allow for scrolling to specify an index.
  7. To save performance, flutter list_view always reuses the rendered item.
  8. Support to keep specifying items without reusing and disposing of them once the item is created.

[!NOTE]
The list item will be reuse when disableCacheItems=false and the invisible item will destroy. This mean, one item may be create or destroy multiple times. So The Item widget must not have any state, as it may lead to unforeseeable issues. If you want work same with list_view which item didn't destroy after create, please put onIsPermanent: (keyOrIndex) => true to FlutterListViewDelegate

FlutterListViewDelegate(
    (BuildContext context, int index) => _renderItem(index),
    childCount: messages.length,
    onItemKey: (index) => messages[index].id.toString(),
    // ...
    disableCacheItems: true,
    onIsPermanent: (keyOrIndex) => true,

Screen

Example

FlutterListView(
      delegate: FlutterListViewDelegate(
    (BuildContext context, int index) =>
        ListTile(title: Text('List Item ${data[index]}')),
    childCount: data.length,
  ))
Jump to index
flutterListViewController.jumpToIndex(100);

OR

/// Declare
FlutterListViewController controller = FlutterListViewController();
...
controller.sliverController
                      .jumpToIndex(100);
...
FlutterListView(
  controller: controller,
  delegate: FlutterListViewDelegate(
    (BuildContext context, int index) => Container(
      color: Colors.white,
      child: ListTile(title: Text('List Item ${data[index]}')),
    ),
    childCount: data.length,
  ))

If you want better user expierence, preferItemHeight or onItemHeight may set to.

  • preferItemHeight The package don't know the item's height, If you don't set, package alway think the item height is 50 util layout the item. If you know the height, you should set it.
  • onItemHeight like preferItemHeight, the function will used to get height of each item util the item layout.
Keep Position
_renderList() {
  return FlutterListView(
      reverse: true,
      delegate: FlutterListViewDelegate(
          (BuildContext context, int index) => Align(
                alignment: Alignment.centerRight,
                child: Padding(
                  padding: const EdgeInsets.all(10.0),
                  child: Container(
                    decoration: const BoxDecoration(
                        color: Colors.blue,
                        borderRadius: BorderRadius.only(
                            topLeft: Radius.circular(20),
                            bottomLeft: Radius.circular(20),
                            bottomRight: Radius.circular(20))),
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Text(
                        chatListContents[index].msg,
                        style: const TextStyle(
                            fontSize: 14.0, color: Colors.white),
                      ),
                    ),
                  ),
                ),
              ),
          childCount: chatListContents.length,
          onItemKey: (index) => chatListContents[index].id.toString(),
          keepPosition: true,
          keepPositionOffset: 80,
          firstItemAlign: FirstItemAlign.end));
}

Notice: Keep positoin need implement onItemKey, the onItemKey used to identify the unique of item. The key should difference with other items' key. We use the key to know what position you insert to current list. if you insert a item before the rendered item, package should increase the scrollOffset.

Sticky header
Widget _renderHeader(String text) {
  return Container(
    color: const Color(0xFFF3F4F5),
    child: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
      child: Text(
        text,
        style: const TextStyle(fontSize: 18, color: Color(0xFF767676)),
      ),
    ),
  );
}

Widget _renderItem(CountryModel itemData) {
  return Padding(
      padding: const EdgeInsets.only(right: 12.0),
      child: ListTile(
          title: Text(itemData.name), trailing: Text(itemData.phoneCode)));
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text("Stick Header")),
    body: FlutterListView(
        delegate: FlutterListViewDelegate(
          (BuildContext context, int index) {
            var data = _countries[index];
            if (data is AlphabetHeader) {
              return _renderHeader(data.alphabet);
            } else {
              return _renderItem(data as CountryModel);
            }
          },
          childCount: _countries.length,
          onItemSticky: (index) => _countries[index] is AlphabetHeader,
        ),
        controller: controller),
  );
}

You can also check doc/stickyHeader.md

Integrate pull_to_refresh
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text("Intergrate pull to refresh in list"),
    ),
    body: SmartRefresher(
      enablePullDown: true,
      enablePullUp: true,
      header: const WaterDropHeader(),
      footer: CustomFooter(
        builder: (context, mode) {
          Widget body;
          if (mode == LoadStatus.idle) {
            body = const Text("pull up load");
          } else if (mode == LoadStatus.loading) {
            body = const CupertinoActivityIndicator();
          } else if (mode == LoadStatus.failed) {
            body = const Text("Load Failed!Click retry!");
          } else if (mode == LoadStatus.canLoading) {
            body = const Text("release to load more");
          } else {
            body = const Text("No more Data");
          }
          return SizedBox(
            height: 55.0,
            child: Center(child: body),
          );
        },
      ),
      controller: _refreshController,
      onRefresh: _onRefresh,
      onLoading: _onLoading,
      child: FlutterListView(
          delegate: FlutterListViewDelegate(
        (BuildContext context, int index) =>
            ListTile(title: Text('List Item ${data[index]}')),
        childCount: data.length,
      )),
    ),
  );
}
Support to keep specifying items without reusing and disposing of them once the item is created.
FlutterListView(
  delegate: FlutterListViewDelegate(
      (BuildContext context, int index) =>
          Item(text: data[index].toString()),
      childCount: data.length,
      // If onItemKey is not given, the key is index
      // The example is indicate the "40" item will not be reused and disposed after it was created
      onIsPermanent: (key) => key == "40"))

所属分类

源码仓库

使用此插件的项目