Flutter-ListTileの選択色

ListTileのパラメータにselectedというパラメータがあるのだけど、それをtrueにした場合の選択色がなんかパッとしないので、他のON/OFFがあるようなUIを参考に良い色がないか試してみようと思う。

現在のListTileの選択時の色

一応、Material2、Material3とライト、ダークの2×2の4種類で試してみた。

  • Material2-ライト
  • Material2-ダーク
  • Material3-ライト
  • Material3-ダーク

Material3での視認性が極端に悪くなる。

これは、バックグラウンド(tileColor)に選択色の設定がnullなためだと思う。そのためtileColorがそのまま使われている。
後は、テキストの色(selectedColor)が識別しづらい、似通った色調の物だからかな。

実際どの色が使われているかまでは調べきれなかった。

ON/OFFがあるUI

ToggleButton、SegmentedButtonとChoiceChipがある。

まずはToggleButton、SegmentedButtonの色はこんな感じになっている。

  • Material2-ライト
  • Material2-ダーク
  • Material3-ライト
  • Material3-ダーク

ChoiceChipはこんな感じ。

  • Material2-ライト
  • Material2-ダーク
  • Material3-ライト
  • Material3-ダーク

ChoiceChipはMaterial2側非選択時の色味がListViewのデフォルトテーマから外れてるので、今回は使用しないようにした。
なおMaterial3側の色味に関してはSegmentedButtonと同じ。

ToggleButtonっぽい色

実装方法。

            final t = Theme.of(context);
            return ListTile(
              selected: selected[index],
              selectedTileColor: t.colorScheme.primary.withOpacity(0.12),
              selectedColor: t.colorScheme.primary,
  • Material2-ライト
  • Material2-ダーク
  • Material3-ライト
  • Material3-ダーク

ToggleButtonsの色は、colorSchemeにwithOpacityで透過度を設定したものを使うようになっている。

SegmentedButtonっぽい色

実装方法。

            final t = Theme.of(context);
            return ListTile(
              selected: selected[index],
              selectedTileColor: t.colorScheme.secondaryContainer,
              selectedColor: t.colorScheme.onSecondaryContainer,
  • Material2-ライト
  • Material2-ダーク
  • Material3-ライト
  • Material3-ダーク

補足

CheckboxListTileを使った場合

ListTileのselectedを使うのではなく、選択専用リストタイルであるCheckboxListTileを使う場合はこんな感じ。
選択中とそうでない場合でListTile/CheckboxListTileを分けて使うようにしている。
ちなみに、ListTileでlongPressで選択処理開始にしている。longPressで選択動作開始というのはよくある操作みたいだ。

                  if (isSelectable) {
                    return CheckboxListTile(
                      value: selected[index],
                      title: Text("list $index"),
                      onChanged: (value) {
                        setState(() {
                          selected[index] = value!;
                          if (!selected.contains(true)) {
                            isSelectable = !isSelectable;
                          }
                        });
                      },
                    );
                  } else {
                    return ListTile(
                      title: Text("list $index"),
                      onLongPress: longPress(index),
                    );
                  }

上の実装を使うと、動きとしてこんな感じになる。

選択状態の表示は以下になる。

  • Material2-ライト
  • Material2-ダーク
  • Material3-ライト
  • Material3-ダーク

Themeのデフォルト探索

前から思うのだけど、各ウィジェットのThemeDataのデフォルトが、ウィジェットソースファイルの内のプライベートクラスやハードコードで用意されているのがほとんど。

そのため、実際の実装を追っていかないと、本当のデフォルトを見つけるのが難しい。

ドキュメントに書いてもらいたいのはもちろんなのだけど、統一的な運用をしてもらいたいと思うようになった。

具体的に言うと、今回chipに関して調べた時に、ChipThemeData.fromDefaultsというデフォルトで使用するファクトリがあった。
ここに渡すパラメータがハードコードされているのはあるのだけど、こういう形で各ThemeDataのファクトリにテーマ別、ライト・ダーク別のデフォルトのテーマデータがあると調べやすいと思った。

コメント

タイトルとURLをコピーしました