codelabs の「Write Your First Flutter App, part 2」ではタップを ListTile 全体で取得していますが、Tile 全体のタップではなく Icon のタップだけを認識するようにします。
codelabs.developers.google.com
結論
IconButton
を使う。
問題
codelabs のサンプルアプリでは、タップイベントをonTap
で取得しています。
onTap
は ListTile へ結びついているため、Tile のどこをタップしてもハートの色が変化します。
これだと Tile 内でタップイベントを分けたい場合は困ります。
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
解決策
trailing
に表示するものをIcon
ではなくIconButton
にすることで簡単に解決できます。
具体的にはtrailing
へIconButton
を指定し、IconButton
の中でIcon
とタップイベント取得用のonPressed
を記載します。
Widget _buildRow(WordPair pair) {
final bool alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: IconButton(
icon: Icon(alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null),
onPressed: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
),
);
}
シンプルに、アイコンをボタンにすればいいよねってことです。
試せていませんが Container
でウィジェットを分けてからクリックリスナーを付けることもできると思います。
参考
ListTile についてはこのページがわかりやすいです。
ListTile class - material library - Dart API