※https://docs.flutter.dev/ui/adaptive-responsive/best-practices のリファレンスBLOGです。
適応型設計に推奨されるベストプラクティスについての話題です。
1.設計上の考慮事項
(1)ウィジェットを分解する
アプリをデザインするときは、大きくて複雑なウィジェットを、小さくてシンプルなものに分解するようにしましょう。
ウィジェットをリファクタリングすると、コアとなるコードを共有でき、それにより適応型UIを採用する複雑さを軽減できます。
また小さなconstウィジェットに分けることで、大きく複雑なウィジェットよりも再構築時間が向上します。
(詳しくは、一般的なアプローチにおけるアダプティブ・デザインの3つのステップをご覧ください。)
(2)各フォームファクタの長所を生かした設計
画面サイズだけでなく、さまざまなフォームファクター独自の長所と短所も考慮する必要があります。マルチプラットフォームアプリがどこでも同じ機能を提供することが必ずしも理想的とは限りません。デバイスのカテゴリーによっては、特定の機能に特化する、あるいは特定の機能を削除することに意味があるかどうかを検討しましょう。
例えば、モバイル機器は持ち運びができ、カメラもついているが、細かいクリエイティブな作業には向いていない。このことを念頭に置くと、モバイルUIではコンテンツのキャプチャと位置情報のタグ付けに重点を置き、タブレットやデスクトップUIではコンテンツの整理や操作に重点を置くことになるかもしれない。
もうひとつの例は、ウェブの共有の障壁が極めて低いことを利用したものです。ウェブアプリをデプロイする場合は、どのディープリンクをサポートするかを決め、それを念頭に置いてナビゲーションのルートを設計しましょう。
重要なのは、各々のプラットフォームが得意なことを考え、活用できる独自の機能があるかどうかを確認することです。
(3)まずタッチインタフェースを洗練させる
優れたタッチUIの構築は、右クリックやスクロールホイール、キーボードショートカットなどの入力アクセラレータがないこともあり、従来のデスクトップUIよりも難しい場合が多い。
この課題にアプローチする1つの方法は、最初は優れたタッチ指向のUIに集中することです。 イテレーションのスピードが速いデスクトップ・ターゲットを使っても、ほとんどのテストを行うことができます。しかし、モバイル・デバイスに頻繁に切り替えて、すべてが正しく感じられるかどうかを確認することを忘れないで下さい。
タッチインターフェースを洗練させた後、マウスユーザーのために視覚的な密度を調整し、すべての追加入力を重ねることができます。他のインプットは、タスクをより速くするためのアクセラレーターのようなものです。考慮すべき重要な点は、ユーザーが特定の入力デバイスを使うときに何を期待するかであり、それをアプリに反映させるよう努力することです。
2.実装の詳細
(1)アプリの向きをロックしてはいけない
適応型アプリは、さまざまなサイズや形状のウィンドウで見栄えがよくなければならない。携帯電話のポートレートモードにアプリをロックすることは、最小実行可能プロダクトの範囲を狭めるのに役立つが、将来的にアプリを適応させるために必要な労力を増大させる可能性があります。
例えば、携帯電話があなたのアプリをフルスクリーンのポートレート・モードでしかレンダリングしないという仮定は保証の限りではありません。マルチウィンドウ・アプリのサポートは一般的になりつつあり、フォルダブルには、複数のアプリを並行して実行することで最適に機能する多くの使用例があります。
どうしてもアプリをポートレート・モードで固定しなければならない場合(しかしそうしない)、画面の物理的な寸法を取得するために、MediaQueryのようなものの代わりにDisplay APIを使用しましょう。
(要約)
・ロックされた画面は、一部のユーザーにとってアクセシビリティの問題になる可能性があります。
・アンドロイドの大判フォーマット層は、最低レベルで縦向きと横向きのサポートを必要とします。
・Androidデバイスはロックされた画面を上書きできます。
・アップルのガイドラインによると、両方の方向性をサポートすることを目指します。
(2)方向に基づいたレイアウトを避ける
MediaQueryのorientationフィールドやOrientationBuilderを使用して、異なるアプリのレイアウトを切り替えることは避けましょう。これは、画面サイズを決定するためにデバイスの種類をチェックしないというガイダンスに似ています。また、デバイスの向きによって、アプリのウィンドウの容量がわかるとは限りません。
その代わりに、MediaQueryのsizeOfかLayoutBuilderを使って下さい。そして、マテリアルが推奨しているようなアダプティブ・ブレークポイントを使用しましょう。
(参考)適応型ブレークポイントについて
Material Designの推奨ブレークポイントでは、推奨される adaptive breakpoints が定義されています。これらのブレークポイントは、アプリが適切なレイアウトを選択できるように設計されており、次のような境界値が設定されています:
小画面 (Small): 画面幅が 0 ~ 600 ピクセル
中画面 (Medium): 画面幅が 600 ~ 840 ピクセル
大画面 (Large): 画面幅が 840 ピクセル以上
このように画面サイズごとにレイアウトを調整することで、ユーザーがどのデバイスを使用していても、適切なレイアウトが表示されるようになります。
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
if (screenWidth >= 840) {
// 大画面レイアウト
return LargeScreenLayout();
} else if (screenWidth >= 600) {
// 中画面レイアウト
return MediumScreenLayout();
} else {
// 小画面レイアウト
return SmallScreenLayout();
}
}
(3)水平方向のスペースをすべて占領しない
ウィンドウの幅いっぱいにボックスやテキストフィールドを表示するアプリは、大画面で実行するとうまく動作しません。
これを避ける方法については、GridViewを使ったレイアウトを参照してください。
(4)ハードウェアタイプの確認を避ける
レイアウトを決定する際に、実行中のデバイスが「電話」なのか「タブレット」なのか、あるいはその他の種類のデバイスなのかをチェックするようなコードを書くのは避けましょう。
アプリが実際にレンダリングされるスペースは、必ずしもデバイスのフルスクリーンサイズに縛られるわけではありません。Flutterは様々なプラットフォームで動作し、あなたのアプリはChromeOSではリサイズ可能なウィンドウで、タブレットではマルチウィンドウモードで他のアプリと並んで、あるいは電話ではピクチャ・イン・ピクチャで動作するかもしれません。そのため、デバイスの種類とアプリのウィンドウサイズは、それほど強く関係していません。
その代わりに、MediaQueryを使用して、アプリが現在実行しているウィンドウのサイズを取得しましょう。
これはUIコードだけに役立つわけではありません。 デバイスの機能を抽象化することがビジネスロジックのコードにどのように役立つかについては、2022年のGoogle I/Oの講演「Flutter lessons for federated plugin development」をチェックして下さい。
(5)様々な入力デバイスをサポート
アプリは基本的なマウス、トラックパッド、キーボードショートカットをサポートすべきです。最も一般的なユーザーフローは、アクセシビリティを確保するためにキーボードナビゲーションをサポートすべきです。
「大画面デバイス」では、ユーザーがキーボードを使う頻度が高くなるため、以下の点が特に重要です:
①キーボードナビゲーションをサポートすること
ユーザーがキーボードのみでアプリを操作できるように、フォーカスの移動や操作方法を設定する。
②UI要素間の移動をスムーズにすること
大画面では表示される情報量が多いため、キーボードを使って効率的にUI要素を移動できるようにすること。
Materialライブラリは、タッチ、マウス、キーボードのインタラクションに対して優れたデフォルト動作をするウィジェットを提供します。カスタムウィジェットにこのサポートを追加する方法については、ユーザ入力とアクセシビリティをご覧ください。
(6)リストの状態を復元する
デバイスの向きが変わってもレイアウトが変わらないリストでスクロール位置を維持するには、PageStorageKey クラスを使用します。 PageStorageKey は、ウィジェットの破棄後にウィジェットの状態をストレージに永続化し、再作成時に状態を復元します。
Wonderousアプリでは、リストの状態をSingleChildScrollViewウィジェットに保存しています。
デバイスの向きが変わるとリストウィジェットのレイアウトが変わる場合、画面の回転に合わせてスクロール位置を変えるために、ちょっとした計算(例)が必要になるかもしれません。
3.アプリの状態を保存する
アプリは、デバイスが回転したり、ウィンドウ・サイズが変わったり、折りたたんだり広げたりしても、アプリの状態を保持または復元する必要があります。 デフォルトでは、アプリは状態を保持する必要があります。
デバイスの設定中にアプリの状態が失われる場合は、アプリが使用するプラグインやネイティブ拡張機能が、大画面などのデバイスの種類をサポートしていることを確認してください。 ネイティブ拡張機能の中には、デバイスの位置が変わると状態が失われるものがあります。
これが実際に起こったケースについての詳細は、Mediumの無料記事「Problem: Folding/unfolding causes state loss in Developing Flutter apps for Large screens」をご覧ください。