实现「滑动清除」效果
“滑动清除”在许多移动应用中都很常见。比如,我们在写一个邮件应用,我们会想让用户能够滑动删除列表中的邮件消息。用户操作时,我们可能需要把这封邮件从收件箱移动到垃圾箱。
Flutter 提供了 Dismissible
Widget 来轻松地实现这个需求。我们一起看一下如下的步骤:
步骤
#-
创建项目列表
-
把每一项打包成一个
Dismissible
Widget -
提供“滞留”提示
1. 创建项目列表
#首先,我们创建一个列表,列表项是能够滑动清除的。至于如何创建列表的更多细节,请参考 长列表的处理 文档。
创建一个数据源
#在我们的例子中,我们需要 20 个样本项来实现列表。为简单起见,我们会生成一个字符串列表。
dart
final items = List<String>.generate(20, (i) => 'Item ${i + 1}');
将数据源转换成一个 List
#首先,我们简单地在屏幕上展示列表中的每一项,用户现在还无法滑动清除它们。
dart
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
)
2. 把每一项打包一个 Dismissible Widget
#在这个步骤中,用户可以通过使用 Dismissible
来删除列表中的某项。
在用户将某一项滑出屏幕后,我们需要将那一项从列表中删除并显示一个 Snackbar。在真实的应用中,你可能需要执行更复杂的逻辑,比如从网页服务或数据库中删除此项。
我们可以通过更新 itemBuilder()
函数来返回一个 Dismissible
widget:
dart
itemBuilder: (context, index) {
final item = items[index];
return Dismissible(
// Each Dismissible must contain a Key. Keys allow Flutter to
// uniquely identify widgets.
key: Key(item),
// Provide a function that tells the app
// what to do after an item has been swiped away.
onDismissed: (direction) {
// Remove the item from the data source.
setState(() {
items.removeAt(index);
});
// Then show a snackbar.
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('$item dismissed')));
},
child: ListTile(
title: Text(item),
),
);
},
3. 提供“滞留”提示
#顾名思义,我们的应用允许用户将列表项滑出列表,但是应用可能没有向用户给出视觉提示,告诉他们操作时发生了什么。要给出提示,表明我们正在删除列表项,就需要在他们将列表项滑出屏幕的时候,展示一个“滞留”提示。这个例子中,我们使用了一个红色背景。
出于这个目的,我们为 Dismissible
设置了一个 background
参数。
dart
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('$item dismissed')));
},
// Show a red background as the item is swiped away.
background: Container(color: Colors.red),
child: ListTile(
title: Text(item),
),
交互式样例
#import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
// MyApp is a StatefulWidget. This allows updating the state of the
// widget when an item is removed.
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
MyAppState createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
final items = List<String>.generate(20, (i) => 'Item ${i + 1}');
@override
Widget build(BuildContext context) {
const title = 'Dismissing Items';
return MaterialApp(
title: title,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return Dismissible(
// Each Dismissible must contain a Key. Keys allow Flutter to
// uniquely identify widgets.
key: Key(item),
// Provide a function that tells the app
// what to do after an item has been swiped away.
onDismissed: (direction) {
// Remove the item from the data source.
setState(() {
items.removeAt(index);
});
// Then show a snackbar.
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('$item dismissed')));
},
// Show a red background as the item is swiped away.
background: Container(color: Colors.red),
child: ListTile(
title: Text(item),
),
);
},
),
),
);
}
}
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-09-02。 查看文档源码 或者 为本页面内容提出建议。