2019年12月3日火曜日

1人 Flutter Advent Calendar 2019:#3 display resolution


前回のソースをQVGAのデバイス実行してみると以下のようになります。

色々とはみ出していてデザインが破綻しています。
ボタンが要素の右の端にあったらもう押すことも出来ないです。

Androidだけではなく、iOSでも画面の解像度にに種類があります。
FlutterではMediaQueryから取得できるsizeはLogical Pixelとされており、Deviceに関係なくだいたい同になるようにいい感じにやってくれます。Androidのdpみたいなもんですね。

しかし、画面自体が小さすぎれば当然、上の画像のように切れてしまいます。

Androidは画像やsizeの定義ファイルを解像度ごとにdirectoryで分けることで、こういった状況に対処します。
https://developer.android.com/training/multiscreen/screendensities?hl=ja

Flutterでも画像に関しては似たような回避策がありそうです。https://flutter.dev/docs/get-started/flutter-for/android-devs#where-do-i-store-my-resolution-dependent-image-files

しかし、widthやheightなどの値については回避策が無さそうでした。
また、デザインツールで出力されるものはwidhtなどが直値で指定されるので、これですべての解像度に対応するのは難しいです。

とはいえ、デザインツールで作成したものからは直値しかわかりません。
アプローチの方法は、Percentで指定する、全体にScaleをする、FlexBoxを利用してサイズに対して柔軟に対応するかだと思います。

Percent指定ですとflutter_screenutil というのがあります。
最初に画面のサイズを決めて、以降はutilityで提供されている関数でwidth/heightを指定します。
基本的には最初に設定したサイズでscaleしているだけになります。
ただ、これだと全体でScreenUtil.getInstance()を利用してサイズを指定しないとダメなので、ちょっと手間ですし、画面の縦横比に従って設定値を調整しないといけません。
https://github.com/matsuhiro/display_resolution_tests/blob/master/lib/main.dart#L189-L275

全体にScaleする方法につい
https://flutter.dev/docs/development/ui/widgets/layout
の中から利用できるものを選んで解決しました。

私の見た中ではFittedBoxが解決策に最適でした。
使った場所はこんなかんじです。
https://github.com/matsuhiro/display_resolution_tests/blob/master/lib/main.dart#L85-L87

全体のレイアウトは崩さずに全体的にScaleされます。
現実には、見栄えのために画面幅に応じたPaddingを入れるのが良いと思います。

これは、最大でも画面幅の90%になるようにPaddingを入れてあります。

これを解像度が大きい端末で実行すると
この様になって、全体にきれいに表示できると思いますし、解決策としても簡単に出来るのではないかと思います。

ここで扱ったサンプルは
https://github.com/matsuhiro/display_resolution_tests
にあります。


FlexBoxに関しては、また違う機会に扱おうと思います。

0 件のコメント:

コメントを投稿