Flutter高性能列表展示插件huge_listview的使用
Flutter高性能列表展示插件 huge_listview
的使用
HugeListView
是一个高性能的列表组件,能够轻松处理任意数量的项。与传统的无限滚动列表不同,它不会不断增加列表项,而是使用固定大小的缓存来保持少量页面(通常是几百个项),并随着新页面的到来丢弃旧页面。
基本介绍
-
特点:
- 只加载和缓存当前需要显示的页面。
- 支持异步加载数据。
- 支持非均匀高度的项,不影响性能。
- 使用自定义的
DraggableScrollbar
来支持滚动条功能。
-
依赖库:
scrollable_positioned_list
:用于支持滚动到特定项。draggable_scrollbar
:用于实现可拖动的滚动条。
使用示例
安装
在 pubspec.yaml
文件中添加依赖:
dependencies:
huge_listview: ^latest_version
然后运行 flutter pub get
来安装依赖。
示例代码
以下是一个完整的示例,展示了如何使用 HugeListView
:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:huge_listview/huge_listview.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_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(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
[@override](/user/override)
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: PageView(
controller: PageController(initialPage: 0),
children: const [
SimplePage(title: 'HugeListView simple demo'),
DeletablePage(title: 'HugeListView deletable demo'),
],
),
),
Container(
color: Colors.blue.shade200,
padding: const EdgeInsets.all(12),
child: Text(
'Swipe to see other pages',
style: Theme.of(context).textTheme.bodyLarge!,
),
)
],
);
}
}
class SimplePage extends StatefulWidget {
final String title;
const SimplePage({super.key, required this.title});
[@override](/user/override)
State<SimplePage> createState() => _SimplePageState();
}
class _SimplePageState extends State<SimplePage> {
static const int PAGE_SIZE = 24;
final scroll = ItemScrollController();
final controller = HugeListViewController(totalItemCount: 999999);
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: HugeListView<String>(
scrollController: scroll,
listViewController: controller,
pageSize: PAGE_SIZE,
startIndex: 0,
pageFuture: (page) => _loadPage(page, PAGE_SIZE),
itemBuilder: (context, index, String entry) {
return ListTile(title: Text(entry));
},
thumbBuilder: DraggableScrollbarThumbs.SemicircleThumb,
placeholderBuilder: (context, index) => buildPlaceholder(),
alwaysVisibleThumb: false,
),
);
}
Future<List<String>> _loadPage(int page, int pageSize) async {
int from = page * pageSize;
int to = min(999999, from + pageSize);
return List.generate(to - from, (index) => 'Item #${from + index}');
}
Widget buildPlaceholder() {
double margin = Random().nextDouble() * 50;
return Padding(
padding: EdgeInsets.fromLTRB(3, 3, 3 + margin, 3),
child: Container(
height: 15,
color: Colors.grey,
),
);
}
}
class DeletablePage extends StatefulWidget {
final String title;
const DeletablePage({super.key, required this.title});
[@override](/user/override)
State<DeletablePage> createState() => _DeletablePageState();
}
class _DeletablePageState extends State<DeletablePage> {
static const int PAGE_SIZE = 24;
final scroll = ItemScrollController();
final controller = HugeListViewController(totalItemCount: 10000);
late List<String> list;
[@override](/user/override)
void initState() {
super.initState();
list = List.generate(controller.totalItemCount + 1,
(index) => 'Item #$index of ${controller.totalItemCount}');
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: HugeListView<String>(
scrollController: scroll,
listViewController: controller,
pageSize: PAGE_SIZE,
startIndex: 0,
pageFuture: (page) => _loadPage(page, PAGE_SIZE),
itemBuilder: (context, index, String entry) {
return ListTile(title: Text(entry));
},
thumbBuilder: DraggableScrollbarThumbs.SemicircleThumb,
placeholderBuilder: (context, index) => buildPlaceholder(),
alwaysVisibleThumb: false,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
final newCount = Random().nextInt(10000) + 10000;
setState(() {
list = List.generate(
newCount + 1, (index) => 'New Item #$index of $newCount');
});
controller.invalidateList(true);
controller.totalItemCount = newCount;
},
tooltip: 'Update list',
child: const Icon(Icons.refresh),
),
);
}
Future<List<String>> _loadPage(int page, int pageSize) async {
int from = page * pageSize;
int to = min(controller.totalItemCount, from + pageSize);
return list.sublist(from, to);
}
Widget buildPlaceholder() {
double margin = Random().nextDouble() * 50;
return Padding(
padding: EdgeInsets.fromLTRB(3, 3, 3 + margin, 3),
child: Container(
height: 15,
color: Colors.grey,
),
);
}
}
关键参数说明
pageSize
: 每页的项数,默认为24。startIndex
: 初始对齐的索引。pageFuture
: 异步加载数据的方法,返回Future<List<T>>
。itemBuilder
: 构建每个项的回调函数。thumbBuilder
: 自定义滚动条样式。placeholderBuilder
: 加载占位符构建器。alwaysVisibleThumb
: 是否始终显示滚动条。
自定义滚动条
如果需要自定义滚动条样式,可以提供一个 thumbBuilder
函数:
thumbBuilder: (Color backgroundColor, Color drawColor, double height, int index, bool alwaysVisibleScrollThumb, Animation<double> thumbAnimation) {
return ScrollBarThumb(backgroundColor, drawColor, height, index.toString(), alwaysVisibleScrollThumb, thumbAnimation);
}
其中 ScrollBarThumb
可以根据需求进行定制,例如:
class ScrollBarThumb extends StatelessWidget {
// ... 省略其他代码 ...
[@override](/user/override)
Widget build(BuildContext context) {
final thumb = Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white.withOpacity(0.8),
),
child: Text(
title,
style: TextStyle(
color: Colors.black,
backgroundColor: Colors.transparent,
fontSize: 14,
),
),
),
Padding(
padding: EdgeInsets.all(2),
),
CustomPaint(
foregroundPainter: _ArrowCustomPainter(drawColor),
child: Material(
elevation: 4.0,
child: Container(constraints: BoxConstraints.tight(Size(height * 0.6, height))),
color: backgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(height),
bottomLeft: Radius.circular(height),
topRight: Radius.circular(4.0),
bottomRight: Radius.circular(4.0),
),
),
),
],
);
return alwaysVisibleScrollThumb ? thumb : SlideFadeTransition(animation: thumbAnimation, child: thumb);
}
}
更多关于Flutter高性能列表展示插件huge_listview的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复