Android デバイスはあらゆる形状とサイズで提供されているため、アプリのレイアウトには柔軟性が必要です。つまり、特定の画面サイズとアスペクト比を想定してレイアウトのディメンションを固定するのではなく、さまざまな画面サイズと向きにレイアウトが柔軟に対応できるようにしなければなりません。
アプリができるだけ多くの画面をサポートしていれば、1 つの APK でさまざまなデバイスに対応できるため、多くのユーザーがそのアプリを利用できます。また、さまざまな画面サイズに柔軟に対応できるようにすれば、デバイスのウィンドウ構成が変更されても(たとえば、ユーザーがマルチウィンドウ モードを有効にしても)アプリがその変更を確実に処理できます。
このページでは、さまざまな画面サイズに対応するための次の方法について説明します。
- レイアウトのサイズを変更できるビュー ディメンションを使用する
- 画面設定に応じて代替 UI レイアウトを作成する
- ビューに合わせて拡大縮小できるビットマップを提供する
ただし、アプリをさまざまな画面サイズに適合させても、必ずしもすべての Android フォーム ファクタとの互換性が確保できるとは限らないことに注意してください。Android Wear、TV、Auto、Chrome OS の各デバイスをサポートするには、追加の手順が必要になります。
さまざまな画面の UI を作成する際のデザインのガイドラインについては、レスポンシブ UI のマテリアル ガイドをご覧ください。
柔軟なレイアウトを作成する
まずサポートしたいのがどのハードウェア プロファイルであっても、画面サイズのわずかな変更に対応できるレイアウトを作成する必要があります。
ConstraintLayout を使用する
さまざまな画面サイズに対応するレスポンシブ レイアウトを作成するには、UI の基本レイアウトとして ConstraintLayout
を使用することをおすすめします。ConstraintLayout
を使用すると、レイアウト内の他のビューとの空間的な関係に従って各ビューの位置とサイズを指定できます。これにより、画面サイズの変化に応じてすべてのビューを同時に移動したり拡大したりできます。
ConstraintLayout
を使ってレイアウトを作成するときは、Android Studio の Layout Editor を使用すると簡単です。このツールを使用すれば XML を手作業で編集する必要がなく、新しいビューをレイアウトにドラッグしたり、その制約を親ビューや他の兄弟ビューに追加したり、ビューのプロパティを編集したりできます(図 1 を参照)。
詳しくは、ConstraintLayout でレスポンシブ UI を作成するをご覧ください。
図 1. ConstraintLayout
ファイルを表示している Android Studio の Layout Editor
ConstraintLayout
によってすべてのレイアウト シナリオが解決されるわけではありませんが(特に、動的に読み込まれるリストについては RecyclerView を使用する必要があります)、どのレイアウトを使用するにしても、レイアウト サイズのハード コーディングは避けることをおすすめします(次のセクションを参照)。
レイアウト サイズのハード コーディングを避ける
さまざまな画面サイズに合わせて調整できる柔軟なレイアウトにするには、ほとんどのビュー コンポーネントの幅と高さに、ハードコードされたサイズではなく "wrap_content"
と "match_parent"
を使用します。
"wrap_content"
を使用すると、コンテンツのサイズに合わせたビューが設定されます。
"match_parent"
を使用すると、親ビューのサイズに合わせてビューが拡大されます。
次に例を示します。
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum" />
ビューの実際のレイアウトはその親ビューや兄弟ビューのその他の属性によって異なりますが、この TextView
では使用可能なすべてのスペースを埋めるように幅が設定され(match_parent
)、ビューの高さはテキストの高さに合わせて設定されます(wrap_content
)。これにより、さまざまな画面サイズとテキストの長さにビューが対応できるようになります。
図 2 は、デバイスの向きに応じて画面の幅が変わったときにテキストビューの幅が "match_parent"
によってどのように調整されるかを示しています。
図 2. 柔軟なテキストビュー
LinearLayout
を使用している場合、レイアウト ウェイトを使用して子ビューを拡大することもできます。これにより、各ビューがその weight 値に比例して残りのスペース全体に表示されます。ただし、入れ子になった LinearLayout
でウェイトを使用する場合、各ビューのサイズを決めるために複数のレイアウトパスが実行されるため UI のパフォーマンスが低下します。ConstraintLayout
ではパフォーマンスに影響を与えずに LinearLayout
を使用してほぼすべてのレイアウトを実現できるので、ぜひレイアウトを ConstraintLayout に変換してみてください。その後、制約チェーンを使用してウェイト レイアウトを定義できます。
代替レイアウトを作成する
レイアウトではビュー内またはビューの周囲のスペースを広げることでさまざまな画面サイズに対応できるとはいえ、すべての画面サイズで最適なユーザー エクスペリエンスを得られるとは限りません。たとえば、スマートフォン用にデザインされた UI の場合、タブレットでは優れたエクスペリエンスを実現できません。このため、特定の画面サイズに合わせて UI デザインを最適化できるように、アプリで代替レイアウト リソースを提供する必要もあります。
図 3. 同じアプリでも画面サイズに合わせて異なるレイアウトを使用できる
画面固有のレイアウトを提供するには、追加の res/layout/
ディレクトリを別のレイアウトを必要とする画面設定ごとに 1 つ作成し、画面設定の修飾子を layout
ディレクトリ名に追加します。たとえば、使用できる幅が 600 dp の画面の場合は layout-w600dp
になります。
この設定修飾子は、アプリ UI が使用できる表示画面スペースを表します。アプリでレイアウトが選択されるとき、システムによって考慮されるのはシステム デコレーション(ナビゲーション バーなど)とウィンドウ構成の変更(ユーザーによるマルチウィンドウ モードの有効化など)です。
Android Studio(バージョン 3.0 以上)で代替レイアウトを作成するには、次の手順を実行します。
- デフォルトのレイアウトを開いて、ツールバーで [Orientation for Preview]
をクリックします。
- プルダウン リストで、[Create Landscape Variant] などの候補バリアントをクリックして作成するか、[Create Other] をクリックします。
- [Create Other] を選択すると、[Select Resource Directory] が表示されます。 左側で画面の修飾子を選択し、その修飾子を [Chosen qualifiers] リストに追加します。修飾子の追加が完了したら、[OK] をクリックします(画面サイズの修飾子については、次のセクションをご覧ください)。
これにより適切なレイアウト ディレクトリに同じレイアウト ファイルが作成されるので、その画面バリアントに対してレイアウトのカスタマイズを開始できます。
最小幅の修飾子を使用する
画面サイズの「最小幅」の修飾子を使用すると、最小幅(密度非依存ピクセル(dp または dip)単位)を持つ画面に対して代替レイアウトを指定できます。
画面非依存ピクセル単位で画面サイズを記述すると、特定の画面ディメンションに合わせてレイアウト デザインを作成でき、ピクセル密度にばらつきが出てくるという心配もありません。
たとえば、スマートフォンやタブレット用に最適化された main_activity
という名前のレイアウトを作成するには、次のようにさまざまなバージョンのファイルをディレクトリに作成します。
res/layout/main_activity.xml # For handsets (smaller than 600dp available width) res/layout-sw600dp/main_activity.xml # For 7” tablets (600dp wide and bigger)
画面の両辺の最小サイズは、デバイスのそのときの向きに関係なく最小幅の修飾子によって指定されます。したがって、レイアウトに使用できる全体的な画面サイズを指定する場合はこの方法が最も簡単です。
他の最小幅の値と、一般的な画面サイズの対応を次に示します。
- 320dp: 通常のスマートフォンの画面(240x320 ldpi、320x480 mdpi、480x800 hdpi など)。
- 480dp: 5 インチ未満の大画面スマートフォン(480x800 mdpi)。
- 600dp: 7 インチ タブレット(600x1024 mdpi)。
- 720dp: 10 インチ タブレット(720x1280 mdpi、800x1280 mdpi など)。
図 4 は、画面 dp 幅と、画面サイズおよび向きが一般的にどのように対応しているかを詳しく示しています。
図 4. さまざまな画面サイズをサポートするための推奨幅ブレークポイント
最小幅の修飾子の数値はすべて密度非依存ピクセルであることにご注意ください。システムが(生ピクセル解像度ではなく)ピクセル密度を認識した後に利用できる画面スペースの大きさが重要であるからです。
利用可能な幅の修飾子を使用する
画面の最小幅に基づいてレイアウトを変更するのではなく、そのとき利用可能な幅または高さに基づいてレイアウトを変更したい場合があります。たとえば、2 ペイン レイアウトがあり、画面の幅が 600 dp 以上のときに必ずこのレイアウトを使用するとします。画面の幅は、デバイスが横向きか縦向きかに応じて変わる可能性があります。この場合は、次のように「利用可能な幅」の修飾子を使用します。
res/layout/main_activity.xml # For handsets (smaller than 600dp available width) res/layout-w600dp/main_activity.xml # For 7” tablets or any screen with 600dp # available width (possibly landscape handsets)
利用可能な高さを考慮する必要がある場合は、「利用可能な高さ」の修飾子を使用して同じことができます。たとえば、画面の高さが 600 dp 以上の画面の場合は layout-h600dp
です。
向きの修飾子を追加する
「最小幅」の修飾子と「利用可能な幅」の修飾子の組み合わせでもすべてのサイズ バリエーションに対応できるかもしれませんが、縦向きと横向きを切り替えてユーザー エクスペリエンスを変更することも可能です。
それには、port
修飾子または land
修飾子をリソース ディレクトリ名に追加します。この修飾子は、必ず他のサイズ修飾子の後ろに追加してください。次に例を示します。
res/layout/main_activity.xml # For handsets res/layout-land/main_activity.xml # For handsets in landscape res/layout-sw600dp/main_activity.xml # For 7” tablets res/layout-sw600dp-land/main_activity.xml # For 7” tablets in landscape
画面設定に関するすべて修飾子について詳しくは、リソースを提供するためのガイドの表 2 をご覧ください。
フラグメントを使って UI コンポーネントをモジュール化する
複数の画面サイズに合わせてアプリを設計するときは、UI の動作をアクティビティ間で不必要に重複させないようにします。そのためには、フラグメントを使用して UI ロジックを個別のコンポーネントに抽出する必要があります。大画面で実行するときは、フラグメントを組み合わせればマルチペイン レイアウトを作成できます。また、スマートフォンで実行するときは、個別のアクティビティに配置することができます。
たとえば、あるタブレットのニュースアプリでは左側に記事のリスト、右側に記事の全文が表示され、左側で記事を選択すると右側の記事ビューが更新されます。一方、スマートフォンではこの 2 つのコンポーネントはそれぞれ別の画面に表示され、リストから記事を選択するとその記事を表示するために画面全体が切り替わります。
詳しくは、フラグメントを使って動的 UI を作成するをご覧ください。
以前のサイズの修飾子を使用して Android 3.1 に対応する
アプリが Android 3.1(API レベル 12)以下に対応する場合は、上記の最小幅の修飾子や利用可能な幅の修飾子の他にも以前のサイズの修飾子を使用する必要があります。
上記の例の場合、2 ペイン レイアウトをさらに大きなデバイスで使用するには、「large」修飾子を使用してバージョン 3.1 以下に対応します。したがって、以前のバージョンでこのレイアウトを実装できるように、次のファイルが使用する場合があります。
res/layout/main_activity.xml # For handsets (smaller than 640dp x 480dp) res/layout-large/main_activity.xml # For small tablets (640dp x 480dp and bigger) res/layout-xlarge/main_activity.xml # For large tablets (960dp x 720dp and bigger)
レイアウト エイリアスを使用する
Android バージョン 3.2 以前と 3.2 以降の両方に対応するには、最小幅の修飾子と large 修飾子の両方をレイアウトに使用する必要があります。このため、res/layout-large/main.xml
という名前のファイルが res/layout-sw600dp/main.xml
と同じになる場合があります。
同じファイルの重複を避けるには、エイリアス ファイルを使用します。 たとえば、次のレイアウトを定義します。
res/layout/main.xml # single-pane layout res/layout/main_twopanes.xml # two-pane layout
次の 2 つのファイルを追加します。
res/values-large/layout.xml
:<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
res/values-sw600dp/layout.xml
:<resources> <item name="main" type="layout">@layout/main_twopanes</item> </resources>
後者の 2 つのファイルは内容は同じですが、実際にはレイアウトを定義していません。単に main
が main_twopanes
のエイリアスになるように設定しています。これらのファイルには large
および sw600dp
セレクタがあるため、Android のバージョンに関係なく大きな画面に適用されます(3.2 以前のタブレットと TV には large
が、3.2 以降には sw600dp
が対応します)。
伸縮可能な 9-patch ビットマップを使用する
サイズが変わるビューの背景としてビットマップを使用すると、その画像は、ビューがその画面やコンテンツのサイズに基づいて拡大または縮小したときに Android によってスケーリングされますが、これによって画像が不鮮明になったり、スケーリングの乱れが発生したりすることがよくあります。対処するには、伸縮可能な領域と不可能な領域を指定する特別な形式の PNG ファイルである 9-patch ビットマップを使用します。
9-patch ビットマップは基本的には標準の PNG ファイルですが、伸縮するピクセルを示す 1 ピクセルの枠線が追加されています(拡張子は .png
ではなく .9.png
です)。図 5 に示すように、左端と上端の黒い線が交差する領域が伸縮可能なビットマップの領域です。
同様に右端と下端で線を追加して、ビュー内でコンテンツを挿入できる安全領域を定義することもできます。
図 5. 9-patch 画像(button.9.png
)
9-patch を背景としてビューに適用すると、ボタンのサイズに合わせて画像が適切に伸縮します。
ビットマップからの 9-patch 画像を作成する際には、サイズ変更可能なビットマップを作成するをご覧ください。
すべての画面サイズでテストする
UI スケールのサイズを確実かつ適切にスケーリングできるように、さまざまな画面サイズでアプリをテストすることが重要です。あらゆる画面サイズに対応する物理デバイスがない場合は、Android Emulator を使用してすべての画像サイズをエミュレートできるようにします。
デバイスを購入することなく物理デバイスでテストしたい場合は、Firebase Test Lab で Google データセンターのデバイスにアクセスできます。
特定の画面サイズのサポートを宣言する
アプリが特定の画面サイズで実行されないようにするには、画面のサイズが変更されるように制限を設定したり、画面の設定に基づいてアプリをインストールできるデバイスを制限したりできます。詳しくは、制限付き画面のサポートを宣言するをご覧ください。