レスポンシブ/アダプティブ レイアウトは、画面サイズに関係なく、最適なユーザー エクスペリエンスを提供します。レスポンシブ/アダプティブ レイアウトを実装して、ビューベースのアプリですべてのディスプレイ サイズ、向き、構成(マルチウィンドウ モードなどのサイズ変更可能な構成を含む)をサポートできるようにします。
レスポンシブ デザイン
さまざまなデバイス フォーム ファクタをサポートするための第一歩は、アプリで使用可能なディスプレイ領域の変化に対応するレイアウトを作成することです。
ConstraintLayout
レスポンシブ レイアウトを作成するには、UI の基本レイアウトとして ConstraintLayout
を使用することをおすすめします。ConstraintLayout
を使用すると、レイアウト内の他のビューとの空間的な関係に従って各ビューの位置とサイズを指定できます。ディスプレイ領域の変化に応じて、すべてのビューを同時に移動したりサイズ変更したりできます。
ConstraintLayout
でレイアウトを作成するときは、Android Studio の Layout Editor を使用すると簡単です。Layout Editor を使用すると、XML を手作業で編集することなく、新しいビューをレイアウトにドラッグし、親ビューや兄弟ビューに対する制約を適用して、ビュー プロパティを設定できます。
![](https://developer.android.com/static/images/screens_support/layout-editor_2x.png?authuser=1&hl=ja)
ConstraintLayout
を表示している Android Studio の Layout Editor。
詳しくは、ConstraintLayout でレスポンシブ UI を作成するをご覧ください。
レスポンシブな幅と高さ
さまざまなディスプレイサイズに対してレイアウトをレスポンシブにするには、ビュー コンポーネントの幅と高さに、ハードコードされた値ではなく wrap_content
、match_parent
、0dp (match constraint)
を使用します。
wrap_content
: ビューに含まれるコンテンツに合わせてサイズが設定されます。match_parent
: ビューは親ビュー内で可能な限り拡大されます。0dp (match constraint)
:ConstraintLayout
で、match_parent
と同様。ビューは、ビューの制約内で利用可能なすべてのスペースを使用します。
例:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum" />
図 4 は、デバイスの向きに応じてディスプレイの幅が変わったときに、TextView
の幅と高さがどのように調整されるかを示しています。
![](https://developer.android.com/static/images/screens_support/layout-match-parent_2x.png?authuser=1&hl=ja)
TextView
。
TextView
では、利用可能なすべてのスペースを埋めるように幅が設定され(match_parent
)、含まれるテキストの高さに合わせて高さが設定されます(wrap_content
)。これにより、さまざまなディスプレイのサイズとテキストの量にビューが対応できるようになります。
LinearLayout
を使用している場合、ビューが利用可能なスペースを比例的に埋めるように、レイアウト ウェイトに基づいて子ビューを拡大することもできます。ただし、ネストされた LinearLayout
でウェイトを使用する場合、各ビューのサイズを決めるために複数のレイアウトパスが行われるため UI のパフォーマンスが低下します。
ConstraintLayout
であれば、パフォーマンスに影響を与えることなく、LinearLayout
で可能なほぼすべてのレイアウトを作成できるため、ネストされた LinearLayout
を ConstraintLayout
に変換します。その後、制約チェーンを使用してウェイト レイアウトを定義できます。
アダプティブ デザイン
アプリのレイアウトは、常にさまざまなディスプレイ サイズに対してレスポンシブである必要があります。ただし、レスポンシブ レイアウトであっても、すべてのデバイスやマルチウィンドウ モードのディスプレイで最適なユーザー エクスペリエンスを提供できるとは限りません。たとえば、スマートフォン用にデザインされた UI は、タブレットでは最適なユーザー エクスペリエンスを提供しません。アダプティブ デザインは、さまざまなディスプレイ サイズ向けに最適化された代替レイアウトを提供します。
リストと詳細 UI の SlidingPaneLayout
一般的に、リストと詳細 UI は異なる画面サイズに応じて異なるユーザー エクスペリエンスを提供します。大画面では、通常リストペインと詳細ペインは横並びで表示されます。リスト内のアイテムを選択すると、アイテムの情報が詳細ペインに表示されます。UI に変化はなく、2 つのペインは横並びのままです。これに対して、小さい画面では 2 つのペインは個別に表示され、各ペインはディスプレイ領域全体を占有します。リストペインのアイテムを選択すると、リストペインに代わって、選択されたアイテムの情報を示す詳細ペインが表示されます。「戻る」操作を行うと、詳細ペインに代わってリストペインが表示されます。
SlidingPaneLayout
は、2 つのユーザー エクスペリエンスのどちらが現在のウィンドウ サイズに適しているかを判断するロジックを管理します。
<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/item_navigation" />
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
SlidingPaneLayout
に含まれる 2 つのビューの layout_width
属性と layout_weight
属性により、SlidingPaneLayout
の動作が決まります。この例では、ウィンドウが両方のビューを表示できる十分な大きさ(幅 580 dp 以上)である場合にペインが横並びに表示されます。ただし、ウィンドウの幅が 580 dp より小さい場合は、一方のペインが他方のペインの上にスライドして、個別にアプリ ウィンドウ全体に表示されます。
ウィンドウの幅が指定した最小幅の合計(580 dp)より大きい場合は、layout_weight
値を使用して 2 つのペインのサイズを比率で指定できます。この例ではウェイトが設定されていないため、リストペインの幅は常に 280 dp です。ただし詳細ペインは、ビューの layout_weight
設定により、常に水平方向の 580 dp を超えるスペースまで表示されます。
代替レイアウト リソース
UI デザインをさまざまなディスプレイサイズに適応させるには、リソース修飾子で識別される代替レイアウトを使用します。
![](https://developer.android.com/static/images/screens_support/sizes-phone-tablet_2x.png?authuser=1&hl=ja)
アプリのソースコードに res/layout/
ディレクトリを追加で作成することで、画面固有のアダプティブ レイアウトを提供できます。異なるレイアウトを必要とする画面構成ごとにディレクトリを作成します。次に、画面構成修飾子を layout
ディレクトリ名に追加します。たとえば、利用可能な幅が 600 dp の画面の場合は layout-w600dp
になります。
この構成修飾子は、アプリの UI に利用できる表示画面スペースを表します。システムは、アプリのレイアウトを選択する際、システム デコレーション(ナビゲーション バーなど)とウィンドウ構成の変更(マルチウィンドウ モードなど)を考慮します。
Android Studio で代替レイアウトを作成するには、ビューを使用して UI を開発するのレイアウト バリアントを使用してさまざまな画面に合わせて最適化するをご覧ください。
最小幅の修飾子
画面サイズの最小幅の修飾子を使用すると、最小幅(密度非依存ピクセル(dp)単位)のディスプレイに対して代替レイアウトを提供できます。
画面サイズを dp 単位で表すと、ピクセル密度の違いを気にすることなく、特定のディスプレイ寸法に合わせたレイアウトを作成できます。
たとえば、スマートフォンやタブレット用に最適化された main_activity
という名前のレイアウトを作成するには、さまざまなバージョンのファイルを個別のディレクトリに作成します。
res/layout/main_activity.xml # For phones (smaller than 600dp smallest width) res/layout-sw600dp/main_activity.xml # For 7" tablets (600dp wide or wider)
画面の両辺の最小サイズは、デバイスのそのときの向きに関係なく最小幅の修飾子によって指定されます。したがって、レイアウトに使用できる全体的な画面サイズを指定する場合はこの方法が最も簡単です。
他の最小幅の値と、一般的な画面サイズの対応を次に示します。
- 320 dp: 小型スマートフォンの画面(240x320 ldpi、320x480 mdpi、480x800 hdpi など)
- 480 dp: 5 インチ未満の大画面スマートフォン(480x800 mdpi)
- 600 dp: 7 インチ タブレット(600x1,024 mdpi)
- 720 dp: 10 インチ タブレット(720x1, 280 mdpi、800x1, 280 mdpi など)
次の図は、画面 dp 幅と、画面サイズおよび向きがどのように対応しているかを詳しく示しています。
![](https://developer.android.com/static/images/screens_support/layout-adaptive-breakpoints_2x.png?authuser=1&hl=ja)
最小幅の修飾子の値は dp です。これは、システムが(生ピクセル解像度ではなく)ピクセル密度を認識した後に利用できるディスプレイ領域の大きさが重要であるためです。
最小幅などのリソース修飾子を使用して指定するサイズは実際の画面サイズではありません。サイズは、アプリのウィンドウで利用可能な幅または高さを dp 単位で指定します。Android システムでは、システム UI(画面下部のシステムバーや画面上部のステータスバーなど)用に画面の一部が使用される場合があるため、画面の一部がレイアウト向けに使用できないことがあります。アプリがマルチウィンドウ モードで使用されている場合、アプリは、アプリを含むウィンドウのサイズにしかアクセスできません。ウィンドウのサイズが変更されると、新しいウィンドウ サイズで構成の変更がトリガーされ、適切なレイアウト ファイルが選択されるようになります。そのため、宣言するリソース修飾子のサイズは、アプリが必要とするスペースのみを指定する必要があります。レイアウト用のスペースを提供する際にシステム UI で使用するスペースが考慮されます。
利用可能な幅の修飾子
ディスプレイの最小幅に基づいてレイアウトを変更するのではなく、利用可能な幅または高さに基づいてレイアウトを変更したい場合があります。たとえば、画面の幅が 600 dp 以上のときに必ず 2 ペイン レイアウトを使用するとします。画面の幅は、デバイスが横向きか縦向きかに応じて変わる可能性があります。その場合は次のように、利用可能な幅の修飾子を使用します。
res/layout/main_activity.xml # For phones (smaller than 600dp available width) res/layout-w600dp/main_activity.xml # For 7" tablets or any screen with 600dp available width # (possibly landscape phones)
アプリで利用可能な高さを重視する場合は、利用可能な高さの修飾子を使用できます。たとえば、画面の高さが 600 dp 以上の画面の場合は layout-h600dp
です。
向きの修飾子
最小幅の修飾子と利用可能な幅の修飾子の組み合わせでもすべてのサイズ バリエーションに対応できるかもしれませんが、縦向きと横向きを切り替えてユーザー エクスペリエンスを変更することも可能です。
それには、port
修飾子または land
修飾子をレイアウト ディレクトリ名に追加します。ただし、向きの修飾子はサイズの修飾子の後に配置してください。例:
res/layout/main_activity.xml # For phones res/layout-land/main_activity.xml # For phones in landscape res/layout-sw600dp/main_activity.xml # For 7" tablets res/layout-sw600dp-land/main_activity.xml # For 7" tablets in landscape
画面構成に関するすべての修飾子について詳しくは、アプリリソースの概要をご覧ください。
ウィンドウ サイズクラス
ウィンドウ サイズクラスは、アダプティブ レイアウトの作成に役立つビューポート ブレークポイントです。ブレークポイントは、アプリで利用可能な表示領域をコンパクト、中程度、拡大に分類します。幅と高さは別々に指定されるため、アプリには常に幅のウィンドウ サイズクラスと高さのウィンドウ サイズクラスがあります。
アダプティブ レイアウトをプログラムで適用する手順は次のとおりです。
- ウィンドウ サイズ クラスのブレークポイントに基づいてレイアウト リソースを作成する
- Jetpack WindowManager ライブラリの
WindowSizeClass#compute()
関数を使用して、アプリの幅と高さのウィンドウ サイズクラスを計算する - 現在のウィンドウ サイズクラスのレイアウト リソースをインフレートする
詳細については、ウィンドウ サイズクラスをご覧ください。
フラグメントによる UI コンポーネントのモジュール化
複数のディスプレイサイズに合わせてアプリを設計するときは、フラグメントを使用して UI ロジックを個別のコンポーネントに抽出し、UI の動作をアクティビティ間で不必要に重複させないようにします。大画面の場合はフラグメントを組み合わせてマルチペイン レイアウトを作成でき、小画面の場合はフラグメントを別々のアクティビティに配置できます。
たとえば、リストと詳細のパターン(前述の SlidingPaneLayout を参照)は、リストを含むフラグメントと、リストアイテムの詳細を含む別のフラグメントで実装できます。大画面ではフラグメントが横並びに表示され、小画面では個別に画面全体に表示されます。
詳しくは、フラグメントの概要をご覧ください。
アクティビティの埋め込み
アプリが複数のアクティビティで構成されている場合、アクティビティの埋め込みを使用すると、アダプティブ UI を簡単に作成できます。
アクティビティの埋め込みは、複数のアクティビティ、または同じアクティビティの複数のインスタンスを、アプリのタスク ウィンドウに同時に表示します。大画面ではアクティビティが横並びに表示され、小画面では積み重ねて表示されます。
XML 構成ファイルを作成することで、アプリでのアクティビティの表示方法を決定します。システムはこのファイルを使用して、ディスプレイサイズに応じた適切な表示を決定します。または、Jetpack WindowManager API を呼び出すこともできます。
アクティビティの埋め込みはデバイスの向きの変更と、折りたたみ式デバイスをサポートします。デバイスの回転や折りたたみと展開に合わせて、アクティビティの積み重ねと積み重ね解除を行います。
詳しくは、アクティビティの埋め込みをご覧ください。
画面サイズとアスペクト比
さまざまな画面サイズとアスペクト比でアプリをテストして、UI が正しくスケーリングされることを確認します。
Android 10(API レベル 29)以降では、さまざまなアスペクト比がサポートされています。折りたたみ式のフォーム ファクタは、折りたたんだときの 21:9 などの縦長画面から、展開したときのアスペクト比 1:1 の正方形まで、さまざまです。
できるだけ多くのデバイスに対応させるには、次に示すうち、できるだけ多くの画面アスペクト比でアプリをテストします。
![](https://developer.android.com/static/images/guide/topics/ui/foldables/fold-screen-ratios.png?authuser=1&hl=ja)
テストするすべての画面サイズのデバイスを用意できない場合は、Android Emulator を使用すると、ほぼすべての画面サイズをエミュレートできます。
実機でテストしたいがデバイスを持っていない場合は、Firebase Test Lab を使用すると、Google データセンターのデバイスにアクセスできます。
参考情報
- マテリアル デザイン - レイアウトについて