Flutter无限分页列表插件listview_infinite_pagination的使用

Flutter无限分页列表插件listview_infinite_pagination的使用

无限分页ListView滚动

这是一个非常轻量级的Flutter包,用于实现带有分页功能的无限滚动ListView。

支持平台

该插件已在iOS、Android和Web上成功测试。

示例

以下示例是从仓库中的示例项目中提取的。更多示例可以在该项目中找到。

无限滚动ListView分页演示

listview_infinite_pagination

功能

  • ✅ 无限滚动ListView
  • ✅ 自动化分页
  • ✅ 可自定义的ListView项小部件
  • ✅ 可自定义的初始加载小部件
  • ✅ 可自定义的更多加载小部件
  • ✅ 可自定义的空列表小部件
  • ✅ 可自定义的错误小部件
  • ✅ 可自定义的到达列表末尾时的小部件
  • ✅ 刷新ListView

入门与使用

使用此包需要两个步骤:

  1. 第一步:创建一个函数来获取数据,使用dataFetcher函数。
  2. 第二步:实现和设计ListView,使用itemBuilder函数。

第一个示例:模型数据样本(字符串列表)

ListviewInfinitePagination<Post>(
  itemBuilder: (index, item) {
    return Text('$index => ${item.title}');
  },
  dataFetcher: (page) => dataFetchMocha(page),
)

// ####### 数据样本模拟函数 dataFetchMocha
Future<List<String>> dataFetchMocha(int page) async {
  List<String> testList = [];
  if (page < 4) {
    for (int i = 1 + (page - 1) * 20; i <= page * 20; i++) {
      testList.add('Item$i of page$page');
    }
  }
  return testList;
}

第二个示例:模型数据样本(API)

ListviewInfinitePagination<Post>(
  itemBuilder: (index, item) {
    return Text('$index => ${item}');
  },
  dataFetcher: (page) => dataFetchApi(page),
)

// ####### API 数据获取函数 dataFetchApi
Future<List<Post>> dataFetchApi(int page) async {
  const String baseUrl = 'https://jsonplaceholder.typicode.com/posts';
  List<Post> testList = [];

  try {
    final res = await http.get(Uri.parse("$_baseUrl?_page=$page&_limit=10"));
    json.decode(res.body).forEach((post) {
      testList.add(Post.fromJson(post));
    });
  } catch (err) {
    if (kDebugMode) {
      print('Something went wrong');
    }
  }
  return testList;
}

完整示例Demo

以下是一个完整的示例代码,展示了如何使用listview_infinite_pagination插件来实现无限分页的ListView。

main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:listview_infinite_pagination/listview_infinite_pagination.dart';

// 引入Post模型文件
import 'model/post.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.amber,
        title: const Text('Demo Listview Infinite Pagination',
            style: TextStyle(color: Colors.black)),
      ),
      body: ListviewInfinitePagination<Post>(
        itemBuilder: (index, item) {
          return Card(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ListTile(
                  leading: const Icon(Icons.image, size: 45),
                  title: Text('#${item.id} ${item.title}'),
                  subtitle: Text('${item.body!} - index $index'),
                ),
              ],
            ),
          );
        },
        dataFetcher: (page) => dataFetchApi(page),

        // ######## 可选配置 ########
        /// 如果你想要刷新并重置列表
        toRefresh: true,

        /// 如果你想要显示自定义的错误小部件
        // onError: (dynamic error) => Center(
        //   child: Text(error.toString()),
        // ),

        /// 如果你想要显示自定义的空列表小部件
        // onEmpty: const Center(
        //   child: Text('This is empty'),
        // ),
      ),
    );
  }
}

// 模拟数据获取函数
Future<List<String>> dataFetch(int page) async {
  await Future.delayed(const Duration(seconds: 0, milliseconds: 2000));
  List<String> testList = [];
  if (page < 4) {
    for (int i = 1 + (page - 1) * 20; i <= page * 20; i++) {
      testList.add('Item$i in page$page');
    }
  }
  return testList;
}

// API数据获取函数
Future<List<Post>> dataFetchApi(int page) async {
  const String baseUrl = 'https://jsonplaceholder.typicode.com/posts';
  List<Post> testList = [];

  final res = await http.get(Uri.parse("$baseUrl?_page=$page&_limit=10"));
  json.decode(res.body).forEach((post) {
    testList.add(Post.fromJson(post));
  });

  return testList;
}

model/post.dart

class Post {
  int? userId;
  int? id;
  String? title;
  String? body;

  Post({this.userId, this.id, this.title, this.body});

  Post.fromJson(Map<String, dynamic> json) {
    userId = json['userId'];
    id = json['id'];
    title = json['title'];
    body = json['body'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = {};
    data['userId'] = userId;
    data['id'] = id;
    data['title'] = title;
    data['body'] = body;
    return data;
  }
}

更多关于Flutter无限分页列表插件listview_infinite_pagination的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter无限分页列表插件listview_infinite_pagination的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,我可以为你提供一个关于如何使用 listview_infinite_pagination 插件来实现 Flutter 中的无限分页列表的示例代码。这个插件允许你在滚动到底部时自动加载更多数据。

首先,确保你已经在 pubspec.yaml 文件中添加了 listview_infinite_pagination 依赖:

dependencies:
  flutter:
    sdk: flutter
  listview_infinite_pagination: ^0.2.0 # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

以下是一个简单的示例代码,展示了如何使用 listview_infinite_pagination 插件来实现无限分页列表:

import 'package:flutter/material.dart';
import 'package:listview_infinite_pagination/listview_infinite_pagination.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Infinite Pagination Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: InfiniteListView(),
    );
  }
}

class InfiniteListView extends StatefulWidget {
  @override
  _InfiniteListViewState createState() => _InfiniteListViewState();
}

class _InfiniteListViewState extends State<InfiniteListView> {
  final List<String> items = [];
  final PaginationController _paginationController = PaginationController();

  @override
  void initState() {
    super.initState();
    // 加载初始数据
    _loadMoreItems();

    // 监听分页控制器以加载更多数据
    _paginationController.addPageRequestListener((pageKey) {
      _loadMoreItems();
    });
  }

  @override
  void dispose() {
    _paginationController.dispose();
    super.dispose();
  }

  Future<void> _loadMoreItems() async {
    // 模拟网络请求,获取更多数据
    final List<String> newItems = List.generate(
      20, // 每页加载的条目数
      (index) => 'Item ${items.length + index + 1}',
    );

    // 将新数据添加到现有数据中
    setState(() {
      items.addAll(newItems);
    });

    // 通知分页控制器页面加载完成
    if (newItems.isNotEmpty) {
      _paginationController.notifyItemLoaded(newItems.length);
    } else {
      // 如果没有更多数据,通知分页控制器没有更多数据可以加载
      _paginationController.notifyNoMoreData();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Infinite Pagination Demo'),
      ),
      body: InfinitePagination(
        controller: _paginationController,
        length: items.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(items[index]),
          );
        },
        pageLoadIndicatorBuilder: (context) {
          return Center(
            child: CircularProgressIndicator(),
          );
        },
        noMoreDataWidget: Center(
          child: Text('No more data'),
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个 InfiniteListView 小部件,它使用 StatefulWidget 来管理状态。
  2. State 中,我们定义了一个 items 列表来存储加载的数据,并创建了一个 PaginationController 实例来控制分页逻辑。
  3. initState 方法中,我们加载初始数据并设置分页控制器监听器,以便在请求更多页面时加载更多数据。
  4. _loadMoreItems 方法模拟了从网络加载数据的过程,并将新数据添加到 items 列表中,然后通知分页控制器数据已加载或没有更多数据。
  5. build 方法中,我们使用 InfinitePagination 小部件来显示列表,并传入分页控制器、数据长度、项目构建器、页面加载指示器构建器和无更多数据小部件。

这个示例展示了如何使用 listview_infinite_pagination 插件来实现一个简单的无限分页列表。你可以根据需要调整代码以适应你的具体需求。

回到顶部