Flutter无限滚动插件endless的使用
Flutter无限滚动插件endless的使用
Endless
一个基于 CustomScrollView
构建的滚动视图库,提供无限加载功能,支持分页(pagination)、流(streams)和Firestore流。以下是该库的一些特性:
特性
-
数据加载:许多可滚动列表应该用一组初始项目填充,并且当用户向下滚动列表时加载更多数据。此库的主要工作就是将这种逻辑抽象为一个易于使用的API,以便构建动态加载更多数据的无限滚动视图。
-
通用滚动元素:许多滚动视图小部件包含一组常见的UI元素,这些元素已经内置到库中,包括用于头部、尾部、加载指示器和空状态的构建器。
-
多种数据源:内置对多种数据源的支持,如分页API和流,以最小化客户端在处理滚动视图时需要进行的数据转换工作。
-
列表+网格:对于移动应用,大多数情况下可滚动视图使用列表,而在桌面端,更多的屏幕空间适合展示网格。该库提供了带共享API的列表和网格视图。
分页
最常见的无限列表数据源通常是某种分页API。该库提供了两个分页小部件 EndlessPaginationListView
和 EndlessPaginationGridView
用于处理这种类型的数据。让我们来看一些基本示例:
基本列表示例
import 'package:flutter/material.dart';
import 'package:endless/endless.dart';
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Endless分页列表视图')),
body: EndlessPaginationListView<String>(
// 一个异步函数,返回要添加到滚动视图中的项目列表。当您滚动超过配置的`extentAfterFactor`时,它会调用`loadMore`来获取更多项目。
loadMore: (pageIndex) async => [...],
// 分页配置决定了何时停止获取项目。
// 滚动视图将因以下原因停止获取更多数据:
// 1. 从`loadMore`返回的项目数小于给定的`pageSize`。
// 2. 它已获取了可选的`maxPages`指定的最大页面数。
paginationDelegate: EndlessPaginationDelegate(
pageSize: 5,
maxPages: 10,
),
itemBuilder: (
context, {
required item,
required index,
required totalItems,
}) {
return Text(item);
},
),
),
);
}
}
基本网格示例
import 'package:flutter/material.dart';
import 'package:endless/endless.dart';
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Endless分页网格视图')),
body: EndlessPaginationGridView<String>(
loadMore: (pageIndex) async => [...],
paginationDelegate: EndlessPaginationDelegate(
pageSize: 5,
maxPages: 10,
),
// 基本列表和网格视图之间的唯一区别在于网格视图指定了其委托,例如在交叉轴上放置多少个项目。
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemBuilder: (
context, {
required item,
required index,
required totalItems,
}) {
return Text(item);
},
),
),
);
}
}
高级示例
Endless
滚动视图支持一组可选的构建器函数,以构建具有以下自顶向下UI的复杂无限滚动列表:
头部 -> headerBuilder
项目 -> itemBuilder
空状态 -> emptyBuilder
加载指示器 -> loadingBuilder
加载更多小部件(例如 TextButton)-> loadMoreBuilder
尾部 -> footerBuilder
import 'package:flutter/material.dart';
import 'package:endless/endless.dart';
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Endless网格视图')),
body: EndlessPaginationListView<String>(
loadMore: (pageIndex) async => [...],
paginationDelegate: EndlessPaginationDelegate(
pageSize: 5,
maxPages: 10,
),
headerBuilder: () => Container(
color: Colors.blue,
child: const Text('头部'),
),
itemBuilder: (
context, {
required item,
required index,
required totalItems,
}) {
return Text(item);
},
),
),
);
}
}
在这个示例中,我们在列表中添加了一个头部。如果我们只想在加载项目后显示头部怎么办?Endless
滚动视图使用了在 Flutter Material 的核心小部件中找到的 StateProperty
模式,例如 MaterialStateProperty
。
Material UI 使用此模式允许核心小部件(如 ElevatedButton
)在处于不同状态(悬停、按下等)时对其进行不同的样式设置。来自文档的基本示例如下:
ElevatedButton(
style: ButtonStyle(
// 将绿色作为所有按钮状态的背景颜色。
backgroundColor: MaterialStateProperty.all<Color>(Colors.green),
),
);
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith<Color>(
// 状态属性传递按钮当前状态的所有状态,
// 以便可以根据状态自定义按钮样式。
(Set<MaterialState> states) {
// 当按钮处于按下状态时,将其颜色变浅。
if (states.contains(MaterialState.pressed))
return Theme.of(context).colorScheme.primary.withOpacity(0.5);
return null;
},
),
),
);
我们使用相同的模式来支持根据滚动视图的状态进行自定义。可能的状态如下:
enum EndlessState { empty, loading, done }
然后我们可以检查滚动视图的当前状态以自定义我们的头部:
import 'package:flutter/material.dart';
import 'package:endless/endless.dart';
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Endless分页列表视图')),
body: EndlessPaginationListView<String>(
loadMore: (pageIndex) async => [...],
paginationDelegate: EndlessPaginationDelegate(
pageSize: 5,
maxPages: 10,
),
// 每个构建器都有一个对应的与状态相关的UI构建器。
headerBuilderState: EndlessStateProperty.resolveWith((states) {
if (states.contains(EndlessState.empty)) {
return null;
}
return Container(
color: Colors.blue,
child: const Text('头部'),
);
}),
itemBuilder: (
context, {
required item,
required index,
required totalItems,
}) {
return Text(item);
},
),
),
);
}
}
完整的 Endless
状态属性帮助器如下:
EndlessStateProperty.all
EndlessStateProperty.loading
EndlessStateProperty.empty
EndlessStateProperty.done
EndlessStateProperty.never
EndlessStateProperty.resolveWith
某些构建器函数具有默认的状态属性行为。例如,emptyBuilder
参数默认被包装在一个 emptyStateBuilder
中,仅在滚动视图为空且不加载时才构建,如下所示:
EndlessStateProperty<Widget?> resolveEmptyBuilderToStateProperty(
Builder<Widget>? builder,
) {
return _resolveBuilderToStateProperty<Widget>(
builder,
(Builder<Widget> builder) =>
EndlessStateProperty.resolveWith<Widget>((context, states) {
if (states.contains(EndlessState.empty) &&
!states.contains(EndlessState.loading)) {
return builder(context);
}
return null;
}),
);
}
这些默认值(如 empty
状态)的目标是为无限滚动视图提供典型的默认行为。如果这不是你想要的空状态默认行为,没问题!你可以随时提供自己的 emptyBuilderState
来覆盖它。
流
基本示例
import 'package:flutter/material.dart';
import 'package:endless/endless.dart';
final streamController = StreamController<List<String>>();
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Endless流列表视图')),
body: EndlessStreamListView<String>(
// 当您滚动超过可配置的`extentAfterFactor`时,调用此函数以告诉流添加更多项。
loadMore: () => [...],
// 流中发出的项目被添加到滚动视图中。一旦流完成,滚动视图就知道不再尝试获取更多项目。
stream: streamController.stream,
itemBuilder: (
context, {
required item,
required index,
required totalItems,
}) {
return Text(item);
},
),
),
);
}
}
更多关于Flutter无限滚动插件endless的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter无限滚动插件endless的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,实现无限滚动功能可以使用endless_list
插件,不过需要注意的是,endless_list
这个具体的插件名称并不是Flutter官方或广泛使用的插件。通常情况下,无限滚动是通过监听列表滚动到底部并动态加载更多数据来实现的。这里我将展示一个基本的实现方法,不使用特定的endless_list
插件,而是使用Flutter内置的ListView.builder
和滚动监听器来实现无限滚动功能。
以下是一个简单的代码示例,展示如何在Flutter中实现无限滚动:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Infinite Scroll Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: InfiniteScrollPage(),
);
}
}
class InfiniteScrollPage extends StatefulWidget {
@override
_InfiniteScrollPageState createState() => _InfiniteScrollPageState();
}
class _InfiniteScrollPageState extends State<InfiniteScrollPage> {
final List<String> items = List.generate(20, (index) => "Item $index");
bool isLoading = false;
ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener(_scrollListener);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _scrollListener() {
if (_scrollController.position.atEdge &&
_scrollController.position.pixels == 0) {
// Scrolled to the top
} else if (_scrollController.position.atEdge &&
!_scrollController.position.outOfRange) {
// Scrolled to the bottom
if (!isLoading) {
setState(() {
isLoading = true;
});
_loadMoreItems();
}
}
}
Future<void> _loadMoreItems() async {
await Future.delayed(Duration(seconds: 2)); // Simulate network delay
setState(() {
int start = items.length;
int end = start + 20;
items.addAll(List.generate(end - start, (index) => "Item ${start + index}"));
isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Infinite Scroll Demo'),
),
body: ListView.builder(
controller: _scrollController,
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
),
);
}
}
代码解释:
-
State管理:
- 使用
StatefulWidget
来管理列表的状态,包括加载更多数据的逻辑。
- 使用
-
滚动监听:
- 使用
ScrollController
来监听列表的滚动事件。 - 在
initState
中注册滚动监听器_scrollListener
。
- 使用
-
滚动事件处理:
_scrollListener
方法检查列表是否滚动到底部。如果是,并且当前没有正在加载的数据,则调用_loadMoreItems
方法来加载更多数据。
-
数据加载:
_loadMoreItems
方法模拟网络延迟(使用Future.delayed
),然后向列表中添加更多数据项。
-
列表构建:
- 使用
ListView.builder
来构建列表,这样可以高效地处理大量数据项。
- 使用
这种方法不使用特定的endless_list
插件,而是利用Flutter的内置功能实现了无限滚动功能。如果你确实需要一个特定的插件,可能需要在pub.dev上搜索并查看相关插件的文档和示例代码。