跳至主要內容

實作滑動關閉

「滑動以移除」的模式在許多行動應用程式中很常見。例如,在撰寫電子郵件應用程式時,您可能會希望允許使用者滑動移除電子郵件訊息,以將其從清單中刪除。

Flutter 透過提供 Dismissible Widget,讓這項任務變得容易。請依照下列步驟學習如何實作滑動以移除功能。

  1. 建立一個項目清單。
  2. 將每個項目包裝在 Dismissible Widget 中。
  3. 提供「滑動後顯示」指示器。

1. 建立項目清單

#

首先,建立一個項目清單。有關如何建立清單的詳細說明,請參閱使用長清單食譜。

建立資料來源

#

在此範例中,您需要 20 個範例項目來進行操作。為了簡化起見,請產生一個字串清單。

dart
final items = List<String>.generate(20, (i) => 'Item ${i + 1}');

將資料來源轉換為清單

#

在螢幕上顯示清單中的每個項目。使用者還無法滑動移除這些項目。

dart
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
    );
  },
)

2. 將每個項目包裝在可滑動移除的 Widget 中

#

在此步驟中,透過使用 Dismissible Widget,讓使用者能夠滑動移除清單中的項目。

在使用者滑動移除項目後,從清單中移除該項目並顯示一個 snackbar。在實際的應用程式中,您可能需要執行更複雜的邏輯,例如從 Web 服務或資料庫中移除該項目。

更新 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),
              ),
            );
          },
        ),
      ),
    );
  }
}