Flutter-VisualDensityの考察

Flutter-ListTileのLeadingとTitleの間隔を調整するでデスクトップとタブレット系でVisualDensityの初期値が違っているという事実を知って、ちょっと驚いた。
このVisualDensityというのは何なのだろうかと思って、ちょっと調べてみた。

VisualDensity

まずどういったものなのかについては、Flutterサイト側に書かれていた。

User input & accessibility
A truly adaptive app also handles differences in how user input works and also programs to help folks with accessibility...

例えば、タッチスクリーンに対応するために、ウィジェットの 「ヒットエリア 」を大きくすることを検討するかもしれない。

入力デバイスによって精度が異なるため、ヒットエリアの大きさも異なります。FlutterのVisualDensityクラスを使えば、アプリケーション全体のビューの密度を簡単に調整できます。例えば、タッチデバイスでボタンを大きくする(つまりタップしやすくする)ことができます。

翻訳すると上のような感じになる。

サンプルの画像でも、VisualDensityの値を大きくする方向で、各ウィジェットが大きくなりタップしやすくなる感じがよく見てとれていた。

初期値

初期値に関して、Flutter-ListTileのLeadingとTitleの間隔を調整するにも書いた通り、Android/iOSが(0, 0)、Windows/MacOS/Linuxが(-2, -2)が初期値として利用されている。

(0, 0)がVisualDensity.standard、(-2, -2)がVisualDensity.compactという定数が用意されていて、これをVisualDensity.adaptivePlatformDensityで取り出し、ThemeData.visualDensityに設定され、ベースの値として使われることになる。

  • 注意
    なぜかIconButtonはMaterial3の場合だけThemeData.visualDensityをデフォルト値として使わず、ThemeData.iconButtonTheme.styleに設定されているButtonStyle.visualDensityを使う設定になっている。

このWindows/MacOS/LinuxがVisualDensity.compactになった経緯がこちらになる。

Desktop needs higher density layouts · Issue #43350 · flutter/flutter
For implementing desktop UIs, higher density layouts are necessary. Layouts meant for touch devices are much larger/loos...

デスクトップ対応を行うことになったとき、standardではマウスポインター操作をするには広すぎて、狭くする必要があるのではないかという提案が出され、それが採用されたようだ。

対応しているウィジェット

API説明書に書かれているウィジェットは、次のようになっている。

Checkbox Chip ElevatedButton IconButton InputDecorator ListTile MaterialButton
OutlinedButton Radio RawMaterialButton TextButton

実際に調べたところは以下の通り。

  • ChipAttributes実装系
    ActionChip ChipChoice ChipFilter ChipInput Chip RawChip
  • ButtonStyle利用系
    ElevatedButton FilledButton OutlinedButton TextButton SegmentedButton
  • ListTile系
    ListTile CheckboxListTile ExpansionTile RadioListTile SwitchListTile
  • MenuStyle利用系
    MenuAnchar
  • CheckBox
  • Radio
  • InputDecorator
  • IconButton
  • MaterialButton
  • RawMaterialButton

IconButtonについて

初期値の注意にも書いたけど、デフォルト値の取り出し先がMaterial3対応でちょっと複雑になっている。

Material3ではvisualDensityを直接指定しない場合、IconButtonThemeのスタイルから取得してくる。それがnullの場合はstandardを利用。

Material2でvisualDensityを直接指定しない場合、Theme.visualDensityから取得してくる。

サンプル的な動作

対応しているウィジェットに関して実装可能なものだけVisualDensityのhorizontalとverticalを変更した時、ウィジェットの見た目がどう変わるかを動画にしてみた。

ChipAttributesとButtonStyle利用系は、horizontalが負の値ではサイズの変化がないみたいだった。
他は、horizontalとverticalの値の変更により大きさが変わっているのがわかる。

コメント

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