【Flutter Widget】「Dismissible」を学ぼう
こんにちは、Saeです。
私は「さえないエンジニア」から「さえたエンジニア」へクラスチェンジするために、日々レベル上げに勤しんでます。
今日は「Dismissible」というWidgetについて解説します。
また今回使用しているサンプルコードはGitHubで公開しております。参考になれば幸いです。
目次
忙しい人のための「Dismissible」
日々忙しさで忙殺されているエンジニアへ向けた「Dismissible」の説明です。
ここだけ見れば、なんとなくわかります。
-
「Dismissible」とは、指定された方向にスライドして、閉じることができるウィジェットのこと
-
使用すると、以下のような挙動になる
-
実装は以下
Dismissible(
// background: 第1背景
// ・backgroundのみ指定 → 両スワイプ時の背景
// ・secondaryBackgroundも指定 → 右スワイプ時の背景
background: Container(
color: Colors.greenAccent,
child: const Align(
alignment: Alignment.centerLeft, child: Icon(Icons.check)),
),
// secondaryBackground: 第2背景
// ・左スワイプ時の背景
secondaryBackground: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerRight, child: Icon(Icons.delete)),
),
// onDismissed: ウィジェットが閉じられたときに呼び出される
onDismissed: (DismissDirection direction) {
// DismissDirection.startToEnd → 右スワイプ背景
if (direction == DismissDirection.startToEnd) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('COMPLETE!')));
}
// DismissDirection.endToStart → 左スワイプ背景
if (direction == DismissDirection.endToStart) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('DELETE!')));
}
setState(() {
items.removeAt(index);
});
},
// key: 表示するリストアイテムにキーを付与し、正常にアイテムが置き換わるようにする
key: ValueKey<int>(items[index]),
// child: 表示するリストアイテム
child: ListTile(
title: Text('Item ${items[index]}'),
),
);
Dismissibleとは
それではここから「Dismissible」について詳しく説明します。
そもそも「Dismissible」とは何なのでしょうか。
公式ドキュメントには以下のように記載されてます。
指定された方向にドラッグして閉じることができるウィジェット。
https://api.flutter.dev/flutter/widgets/Dismissible-class.html
公式docに記載の通り、DismissibleというWidgetで囲むと
「指定された方向にスライドして、閉じることができるウィジェット」になります。
Dismissibleの使い方
ではDismissibleの使い方を、実際のコードと合わせて説明します。
0. 事前準備
まずはDismissibleを囲むために必要なクラス、リストアイテムを作成しましょう。
import 'package:flutter/material.dart';
// リストアイテムを置き換えるためにStatefulWidgetで作成
class DismissibleExample extends StatefulWidget {
const DismissibleExample({Key? key}) : super(key: key);
State<DismissibleExample> createState() => _DismissibleExampleState();
}
class _DismissibleExampleState extends State<DismissibleExample> {
// 表示するリストアイテムを作成
List<int> items = List<int>.generate(100, (index) => index);
Widget build(BuildContext context) {
return Scaffold(
// 作成したリストアイテムを表示
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Item ${items[index]}'),
);
},
),
);
}
}
ここまで実装すると以下のようにリスト表示されます
1. DismissibleでWidgetを囲む
それではここから実際に「Dismissible」を使っていきましょう。
まずDismissibleを実装する際に、最低限必要になってくるプロパティを使用して実装します。
必要になってくるプロパティは以下です。
プロパティ | 内容 |
---|---|
background | スワイプ時の背景 |
onDismissed | ウィジェットが閉じられたときに呼び出される |
key | 表示するリストアイテムにキーを付与し、正常にアイテムが置き換わるようにする |
child | 表示するリストアイテム |
以下実装コードになります。
Widget build(BuildContext context) {
return Scaffold(
// 作成したリストアイテムを表示
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Dismissible(
// background: スワイプ時の背景
background: Container(
color: Colors.greenAccent,
child: const Align(
alignment: Alignment.center, child: Icon(Icons.check)),
),
// onDismissed: ウィジェットが閉じられたときに呼び出される
onDismissed: (DismissDirection direction) {
setState(() {
// スワイプしたリストのアイテムを削除
items.removeAt(index);
});
},
// key: 表示するリストアイテムにキーを付与し、正常にアイテムが置き換わるようにする
key: ValueKey<int>(items[index]),
// child: 表示するリストアイテム
child: ListTile(
title: Text('Item ${items[index]}'),
),
);
},
),
);
}
上記を実装すると以下のような挙動になります。
2. Dismissibleにプロパティを追加する
ただ上記の実装コードだと、挙動的に少し違和感を感じる部分もあるかと思います。
そこで以下の内容を追加で実装していきます。
- 左スワイプ時には、完了アイコンを表示
- 右スワイプ時には、削除アイコンを表示
- 完了、削除時にはスナックバーを表示
追加するには以下のプロパティを追加・編集していきます。
プロパティ | 内容 |
---|---|
(追加)secondaryBackground | 左スワイプ時の背景 |
(編集)onDismissed | ウィジェットが閉じられたときの方向を引数から取得 |
以下実装コードになります。
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Dismissible(
// background: 第1背景
// ・backgroundのみ指定 → 両スワイプ時の背景
// ・secondaryBackgroundも指定 → 右スワイプ時の背景
background: Container(
color: Colors.greenAccent,
child: const Align(
alignment: Alignment.centerLeft, child: Icon(Icons.check)),
),
// secondaryBackground: 第2背景
// ・左スワイプ時の背景
secondaryBackground: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerRight, child: Icon(Icons.delete)),
),
// onDismissed: ウィジェットが閉じられたときに呼び出される
onDismissed: (DismissDirection direction) {
// DismissDirection.startToEnd → 右スワイプ背景
if (direction == DismissDirection.startToEnd) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('COMPLETE!')));
}
// DismissDirection.endToStart → 左スワイプ背景
if (direction == DismissDirection.endToStart) {
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('DELETE!')));
}
setState(() {
items.removeAt(index);
});
},
// key: 表示するリストアイテムにキーを付与し、正常にアイテムが置き換わるようにする
key: ValueKey<int>(items[index]),
// child: 表示するリストアイテム
child: ListTile(
title: Text('Item ${items[index]}'),
),
);
},
),
);
}
上記を実装すると以下のような挙動になります。
まとめ
いかがでしたでしょうか。
Dismissibleを使えば、シンプルなコードで指定された方向へ閉じるウィジェットを作成できることがわかったと思います。
みなさんもDismissibleを活用し、素敵なFlutterライフをお過ごしくださいませ。では〜。
Discussion