實現「滑動清除」效果
『滑動清除』在許多移動應用中都很常見。比如,我們在寫一個郵件應用,我們會想讓使用者能夠滑動刪除清單中的郵件訊息。使用者操作時,我們可能需要把這封郵件從收件箱移動到垃圾箱。
Flutter 提供了 Dismissible
Widget 來輕鬆地實現這個需求。我們一起看一下如下的步驟:
步驟
-
建立專案清單
-
把每一項打包成一個
Dismissible
Widget -
提供『滯留』提示
1. 建立專案清單
首先,我們建立一個清單,清單項是能夠滑動清除的。至於如何建立清單的更多細節,請參考 長清單的處理 文件。
建立一個資料來源
在我們的例子中,我們需要 20 個樣本項來實現清單。為簡單起見,我們會生成一個字串清單。
final items = List<String>.generate(20, (i) => 'Item ${i + 1}');
將資料來源轉換成一個 List
首先,我們簡單地在螢幕上展示清單中的每一項,使用者現在還無法滑動清除它們。
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(items[index]),
);
},
)
2. 把每一項打包一個 Dismissible Widget
在這個步驟中,使用者可以透過使用 Dismissible
來刪除清單中的某項。
在使用者將某一項滑出螢幕後,我們需要將那一項從清單中刪除並顯示一個 Snackbar。在真實的應用中,你可能需要執行更復雜的邏輯,比如從網頁服務或資料庫中刪除此項。
我們可以透過更新 itemBuilder()
函式來回傳一個 Dismissible
widget:
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
引數。
lib/{step2.dart (Dismissible) → main.dart (Dismissible)}
@@ -16,6 +16,8 @@
|
|
16
16
|
ScaffoldMessenger.of(context)
|
17
17
|
.showSnackBar(SnackBar(content: Text('$item dismissed')));
|
18
18
|
},
|
19
|
+
// Show a red background as the item is swiped away.
|
20
|
+
background: Container(color: Colors.red),
|
19
21
|
child: ListTile(
|
20
22
|
title: Text(item),
|
21
23
|
),
|
互動式範例
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),
),
);
},
),
),
);
}
}