Flutter分组粘性列表插件sticky_grouped_list_plus的使用
Flutter分组粘性列表插件sticky_grouped_list_plus的使用
特点
- 轻松创建类似聊天界面。
- 列表项可以被分组。
- 每个组可以设置单独的头部。
- 粘性头部支持浮动选项。
- 所有
ScrollablePositionedList
字段均可使用。
开始使用
在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
sticky_grouped_list: ^3.1.0
在你的Dart文件中导入库:
import 'package:sticky_grouped_list/sticky_grouped_list.dart';
创建一个StickyGroupedListView
组件:
final GroupedItemScrollController itemScrollController = GroupedItemScrollController();
StickyGroupedListView<dynamic, String>(
elements: _elements,
sort: true,
groupBy: (dynamic element) => element['group'],
groupSeparatorBuilder: (dynamic element) => Text(element['group']),
itemBuilder: (context, dynamic element) => Text(element['name']),
itemComparator: (e1, e2) => e1['name'].compareTo(e2['name']), // 可选
elementIdentifier: (element) => element.name, // 可选 - 见下文
itemScrollController: itemScrollController, // 可选
order: StickyGroupedListOrder.ASC, // 可选
);
如果你使用了GroupedItemScrollController
,可以通过索引来程序化滚动到特定位置:
- 通过索引滚动到指定位置:
itemScrollController.scrollTo(index: 4, duration: Duration(seconds: 2));
itemScrollController.jumpTo(index: 4);
- 通过预定义的元素标识符滚动到指定元素。标识符是一个函数,接受一个元素并返回一个唯一的标识符:
final GroupedItemScrollController itemScrollController = GroupedItemScrollController();
StickyGroupedListView<dynamic, String>(
elements: _elements,
elementIdentifier: (element) => element.name,
itemScrollController: itemScrollController,
[...]
);
final scrolledItemIndex = itemScrollController.scrollToElement(identifier: 'item-1', duration: Duration(seconds: 2));
final scrolledItemIndexOnJump = itemScrollController.jumpToElement(identifier: 'item-2');
参数
名称 | 描述 | 必需 | 默认值 |
---|---|---|---|
elements |
需要显示的数据列表 | 是 | - |
itemBuilder / indexedItemBuilder |
返回一个定义项的Widget的函数。indexedItemBuilder 提供当前索引作为参数。如果两者都定义了,优先使用indexedItemBuilder 。 |
是,两者之一 | - |
groupBy |
映射元素到其分组值的函数 | 是 | - |
groupSeparatorBuilder |
获取元素并返回一个定义分组头部分隔符的Widget的函数 | 是 | - |
separator |
定义组内项之间分隔符的Widget | 否 | 无分隔符 |
floatingHeader |
设置为true 时,粘性头部将浮动在列表上方 |
否 | false |
stickyHeaderBackgroundColor |
定义粘性头部的背景颜色 | 否 | Color(0xffF7F7F7) |
itemScrollController |
需要提供一个GroupedItemScrollController 而不是ItemScrollController 。 |
否 | - |
elementIdentifier |
由itemScrollController 使用,定义每个元素的唯一标识符。 |
否 | - |
order |
改变分组排序顺序。设置为StickyGroupedListOrder.DESC 以反转分组排序。 |
否 | StickyGroupedListOrder.ASC |
groupComparator |
可用于定义自定义的分组排序。否则使用自然排序。 | 否 | - |
itemComparator |
可用于定义自定义的元素内部排序。否则使用自然排序。 | 否 | - |
reverse |
与阅读方向相反滚动(从底部开始向上滚动)。与scrollable_positioned_list 相同。 |
否 | false |
sort |
启用按给定顺序排序。 | 否 | true |
注意:GroupedItemScrollController.scrollTo()
和 GroupedItemScrollController.jumpTo()
自动设置alignment
,使项目完全可见并位于组头部下方。这两种方法都有一个可选的automaticAlignment
参数,如果指定了alignment
,则需要将其设置为true
。
强调:可以使用ScrollablePositionedList.builder
的所有字段。
聊天对话框
轻松创建聊天对话框。只需将reverse
设置为true
并将order
设置为StickyGroupedListOrder.DESC
。可以在示例中找到完整示例。初始状态下,列表将滚动到末尾,因此滚动方向将与阅读方向相反。
区别
grouped_list
包中的列表视图基于默认的Flutter列表视图和银色列表。而sticky_grouped_list
基于scrollable_positioned_list
,这使得可以程序化滚动到列表中的特定位置。因此,如果你需要能够程序化滚动列表,请使用此包;否则,建议使用grouped_list
包。
使用的包
包名 | 版权声明 | 许可证 |
---|---|---|
scrollable_positioned_list | Copyright 2018 the Dart project authors, Inc. All rights reserved | BSD 3-Clause “New” or “Revised” License |
示例代码
main.dart
import 'package:flutter/material.dart';
import 'package:sticky_grouped_list/sticky_grouped_list.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
示例数据
List<Map<String, dynamic>> _elements = [
{'name': 'Alice', 'group': 'A'},
{'name': 'Bob', 'group': 'B'},
{'name': 'Charlie', 'group': 'A'},
{'name': 'David', 'group': 'B'},
];
使用示例数据的代码
import 'package:flutter/material.dart';
import 'package:sticky_grouped_list/sticky_grouped_list.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Map<String, dynamic>> _elements = [
{'name': 'Alice', 'group': 'A'},
{'name': 'Bob', 'group': 'B'},
{'name': 'Charlie', 'group': 'A'},
{'name': 'David', 'group': 'B'},
];
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: StickyGroupedListView<dynamic, String>(
elements: _elements,
sort: true,
groupBy: (dynamic element) => element['group'],
groupSeparatorBuilder: (dynamic element) => Text(element['group']),
itemBuilder: (context, dynamic element) => Text(element['name']),
itemComparator: (e1, e2) => e1['name'].compareTo(e2['name']),
elementIdentifier: (element) => element['name'],
itemScrollController: GroupedItemScrollController(),
order: StickyGroupedListOrder.ASC,
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
更多关于Flutter分组粘性列表插件sticky_grouped_list_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html