Flutter分页列表插件paginated_list的使用
Flutter分页列表插件paginated_list的使用
paginated_list
paginated_list
是一个Flutter插件,它提供了一个可滚动容器来显示项目列表。该列表可以水平或垂直滚动。此外,这个列表可以是无限的,即当用户滚动时,它会请求更多的项目。
Introduction
此库通过提供易于访问的函数使分页更简单。以下是一些关键特性的说明:
- 类型化:
PaginatedList<T>
接收一个泛型类型参数,这决定了构建器接收到的第一个参数类型以及items
列表中的元素类型。 - 加载更多:当最后一个项目完全可见时,会调用
onLoadMore
函数,在这里应该放置添加更多项目的逻辑。 - 最近搜索按钮(可选):如果设置
isRecentSearch
为true,则会在组件右上角添加一个IconButton,默认情况下允许删除旧搜索记录。 - 是否为最后一页:通过
isLastPage
布尔值来判断是否已经显示了所有数据,如果是,则不会展示加载指示器且不触发加载更多操作。 - 主布局:
PaginatedList
内部使用的是ListView.builder()
,因此可能需要在外层包裹Expanded
或者指定尺寸的SizedBox
以确保其正确渲染。
示例GIF
Usage
以下是PaginatedList
的基本用法示例:
import 'package:flutter/material.dart';
import 'package:paginated_list/paginated_list.dart';
class MovieList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PaginatedList<Movie>(
loadingIndicator: const Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: CircularProgressIndicator(color: Colors.black),
),
),
items: state.movies, // 假设state.movies是从状态管理中获取的数据
isRecentSearch: false,
isLastPage: state.isLastPage, // 假设state.isLastPage是一个布尔变量,表示是否到达了最后一页
onLoadMore: (index) => context.read<MovieBloc>().loadMore(),
builder: (movie, index) => ListTile(
title: Text(movie.title),
subtitle: Text(movie.overview),
leading: Image.network(movie.posterPath ?? ''),
),
);
}
}
对于网格视图,你可以使用PaginatedGrid
:
import 'package:flutter/material.dart';
import 'package:paginated_list/paginated_list.dart';
class MovieGrid extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PaginatedGrid<Movie>(
loadingIndicator: const Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: CircularProgressIndicator(color: Colors.black),
),
),
items: state.movies, // 假设state.movies是从状态管理中获取的数据
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
childAspectRatio: 0.7,
),
isLastPage: state.isLastPage, // 假设state.isLastPage是一个布尔变量,表示是否到达了最后一页
onLoadMore: () => context.read<MovieBloc>().loadMore(),
builder: (movie, index) => Card(
child: Column(
children: [
Image.network(movie.posterPath ?? ''),
Text(movie.title),
Text(movie.overview),
],
),
),
);
}
}
完整示例Demo
为了更好地理解如何使用paginated_list
插件,下面提供了一个完整的例子,包括应用程序入口点和电影列表页面。
// main.dart
import 'package:flutter/material.dart';
import 'package:paginated_list/paginated_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Paginated List Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MovieListScreen(),
);
}
}
class MovieListScreen extends StatefulWidget {
@override
_MovieListScreenState createState() => _MovieListScreenState();
}
class _MovieListScreenState extends State<MovieListScreen> {
final List<Movie> movies = [];
bool isLastPage = false;
@override
void initState() {
super.initState();
loadMoreMovies();
}
Future<void> loadMoreMovies() async {
// 模拟网络请求
await Future.delayed(Duration(seconds: 2));
if (movies.length >= 20) {
setState(() {
isLastPage = true;
});
return;
}
final newMovies = List.generate(10, (index) => Movie(
title: 'Movie ${movies.length + index + 1}',
overview: 'Overview of movie ${movies.length + index + 1}',
posterPath: 'https://via.placeholder.com/150',
));
setState(() {
movies.addAll(newMovies);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Movies'),
),
body: PaginatedList<Movie>(
loadingIndicator: const Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: CircularProgressIndicator(color: Colors.black),
),
),
items: movies,
isRecentSearch: false,
isLastPage: isLastPage,
onLoadMore: (_) => loadMoreMovies(),
builder: (movie, index) => ListTile(
title: Text(movie.title),
subtitle: Text(movie.overview),
leading: Image.network(movie.posterPath),
),
),
);
}
}
class Movie {
final String title;
final String overview;
final String posterPath;
Movie({required this.title, required this.overview, required this.posterPath});
}
在这个例子中,我们创建了一个简单的电影列表应用。每次滚动到底部时都会加载更多电影,并在达到最后一页后停止加载。
更多关于Flutter分页列表插件paginated_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter分页列表插件paginated_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用paginated_list
插件来实现分页列表的一个示例代码。paginated_list
插件可以帮助你轻松实现分页加载数据的功能。
首先,确保你已经在pubspec.yaml
文件中添加了paginated_list
依赖:
dependencies:
flutter:
sdk: flutter
paginated_list: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来是一个完整的示例代码,展示如何使用paginated_list
插件:
import 'package:flutter/material.dart';
import 'package:paginated_list/paginated_list.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Paginated List Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final PaginatedListController<int> _controller = PaginatedListController<int>();
@override
void initState() {
super.initState();
// 初始化分页加载数据
_loadData();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _loadData() async {
// 模拟分页加载数据
final Future<List<int>> fetchPage(int page) async {
await Future.delayed(Duration(seconds: 1)); // 模拟网络延迟
return List.generate(10, (index) => (page - 1) * 10 + index + 1);
}
// 设置分页加载逻辑
_controller.setLoadMoreItems(() async {
final int currentPage = _controller.page + 1;
final List<int> newItems = await fetchPage(currentPage);
return PaginatedListLoadResult.success(newItems);
});
// 初始加载第一页数据
_controller.setItems(await fetchPage(1));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Paginated List Demo'),
),
body: PaginatedListView<int>(
controller: _controller,
itemBuilder: (context, item, index) {
return ListTile(
title: Text('Item ${item}'),
);
},
separatorBuilder: (context, index) => Divider(),
errorWidget: (context, error, retry) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Error: $error'),
SizedBox(height: 10),
ElevatedButton(
onPressed: retry,
child: Text('Retry'),
),
],
),
);
},
emptyWidget: Center(child: Text('No data')),
),
);
}
}
代码解释
-
依赖导入:
- 导入
flutter
和paginated_list
包。
- 导入
-
主应用:
MyApp
是一个简单的MaterialApp
,设置了主题和主页MyHomePage
。
-
主页:
MyHomePage
是一个StatefulWidget
,包含一个PaginatedListController<int>
用于管理分页数据。- 在
initState
中调用_loadData
方法初始化分页加载逻辑。 - 在
dispose
中释放PaginatedListController
资源。
-
数据加载:
_loadData
方法模拟分页加载数据,使用fetchPage
函数模拟网络请求。- 设置分页加载逻辑,通过
_controller.setLoadMoreItems
方法。 - 初始加载第一页数据,通过
_controller.setItems
方法。
-
UI构建:
- 使用
PaginatedListView
构建分页列表,传入controller
、itemBuilder
、separatorBuilder
、errorWidget
和emptyWidget
。 itemBuilder
定义了每个列表项的UI。separatorBuilder
定义了列表项之间的分隔符。errorWidget
定义了加载数据出错时的UI。emptyWidget
定义了数据为空时的UI。
- 使用
这个示例展示了如何使用paginated_list
插件实现一个简单的分页列表功能。你可以根据实际需求调整数据加载逻辑和UI样式。