1. はじめに
この Codelab では、スマートフォン、タブレット、折りたたみ式デバイス向けのアダプティブ アプリを作成する方法と、Jetpack Compose で到達性を高める方法を学びます。また、マテリアル 3 のコンポーネントの使用とテーマ設定に関するベスト プラクティスについても学習します。
詳細に入る前に、適応性とは何かを理解しましょう。
適応性
アプリの UI は、さまざまなウィンドウ サイズ、向き、フォーム ファクタに対応するためにレスポンシブである必要があります。アダプティブ レイアウトは、使用可能な画面スペースに応じて変化します。この変化は、スペースを埋めるための単純なレイアウト調整から、それぞれのナビゲーション スタイルの選択、追加の空間を活用するためのレイアウトの完全な変更まで、多岐にわたります。
詳しくは、アダプティブ デザインをご覧ください。
この Codelab では、Jetpack Compose を使用する際の適応性についての考え方と使い方を学びます。Reply という、あらゆる種類の画面で適応性を実現する方法と、適応性と到達性を組み合わせて、最適なユーザー エクスペリエンスを提供する方法について説明するアプリを作成します。
学習内容
- Jetpack Compose ですべてのウィンドウ サイズをターゲットとするアプリを設計する方法
- アプリをさまざまな折りたたみ式デバイスに対応させる方法
- さまざまなナビゲーションを使って到達性とアクセシビリティを向上させる方法
- マテリアル 3 コンポーネントを使用して、すべてのウィンドウ サイズに最適なエクスペリエンスを提供する方法
必要なもの
- Android Studio の最新の安定版
- Android 13 でサイズ変更可能な仮想デバイス。
- Kotlin に関する知識
- Compose に関する基礎知識(
@Composable
アノテーションなど) - Compose レイアウト(
Row
やColumn
など)に関する基本的な知識。 - 修飾子(
Modifier.padding()
など)に関する基本的な知識。
この Codelab では、サイズ変更可能なエミュレータを使用します。これにより、さまざまな種類のデバイスとウィンドウ サイズを切り替えることができます。
Compose に慣れていない場合は、この Codelab の前に、Jetpack Compose の基本の Codelab を受講することを検討してください。
作成するアプリの概要
- 適応可能なデザイン、さまざまなマテリアル ナビゲーション、最適な画面スペースの使用に関するベスト プラクティスを採用している Reply というインタラクティブなメール クライアント アプリ。
2. セットアップする
この Codelab のコードを取得するには、コマンドラインから GitHub リポジトリのクローンを作成します。
git clone https://github.com/android/codelab-android-compose.git cd codelab-android-compose/AdaptiveUiCodelab
または、リポジトリを ZIP ファイルとしてダウンロードすることもできます。
main ブランチのコードから始め、ご自身のペースで順を追って Codelab を進めることをおすすめします。
Android Studio でプロジェクトを開く
- [Welcome to Android Studio] ウィンドウで、 [Open an Existing Project] を選択します。
<Download Location>/AdaptiveUiCodelab
フォルダを選択します(build.gradle
が格納されているAdaptiveUiCodelab
ディレクトリを選択してください)。- Android Studio にプロジェクトがインポートされたら、
main
ブランチを実行できるかどうかをテストします。
start コードを確認する
main ブランチのコードには、ui
パッケージが含まれています。そのパッケージ内の次のファイルを使用します。
MainActivity.kt
- アプリを起動するエントリ ポイント アクティビティ。ReplyApp.kt
- メイン画面の UI コンポーザブルがあります。ReplyHomeViewModel.kt
- アプリ コンテンツのデータと UI の状態を提供します。ReplyListContent.kt
- リストと詳細画面を提供するためのコンポーザブルがあります。
このアプリをサイズ変更可能なエミュレータで実行し、スマートフォンやタブレットなどのさまざまなデバイスタイプを試しても、UI は与えられたスペースに広がるだけで、画面スペースを使用したり、到達性に関するエルゴノミクスを提供したりすることはありません。
更新すると、画面スペースを有効活用して、ユーザビリティを向上させ、全体的なユーザー エクスペリエンスを改善できます。
3. アプリを自動適応にする
このセクションでは、アプリを適応可能にすることの意味と、それを容易にするためにマテリアル 3 に用意されているコンポーネントについて説明します。また、スマートフォン、タブレット、大型タブレット、折りたたみ式デバイスなど、ターゲットとする画面の種類と状態についても説明します。
まず、ウィンドウ サイズ、折りたたみ形状、さまざまなナビゲーション オプションの基本について説明します。その後、アプリでこれらの API を使用して、アプリの適応性を高めることができます。
ウィンドウ サイズ
Android デバイスには、スマートフォンから折りたたみ式デバイス、タブレット、ChromeOS デバイスまで、あらゆる形とサイズがあります。できるだけ多くのウィンドウ サイズをサポートするには、UI をレスポンシブかつアダプティブにする必要があります。アプリの UI を変更する適切なしきい値を見つけられるように、ウィンドウ サイズクラスと呼ばれる事前定義のサイズクラス(コンパクト、中程度、拡大)にデバイスを分類するためのブレークポイント値が定義されています。ウィンドウ サイズクラスは、アプリのレスポンシブ レイアウト、アダプティブ レイアウトを設計、開発、テストする際に役立つ独自のビューポート ブレークポイントのセットです。
これらのカテゴリは、柔軟性とレイアウトのシンプルさのバランスを取りつつ、固有のケースに合わせてアプリを最適化できるように、特別に選択されたものです。ウィンドウ サイズクラスは、アプリが利用可能な画面スペースによって常に決まり、マルチタスクや他の分割が行われている場合は、物理画面全体ではない場合があります。
幅と高さの両方は個別に分類されるため、どの時点でも、アプリにはウィンドウ サイズクラスが 2 つ(幅用と高さ用)あります。通常、縦方向のスクロールは頻繁に行われるため、利用可能な幅は利用可能な高さよりも重要です。そのため、この場合は幅サイズクラスも使用します。
折りたたみ状態
折りたたみ式デバイスでは、さまざまなサイズとヒンジがあるため、アプリが対応できる状況がさらに増えます。ヒンジでディスプレイの一部が見えにくくなるため、その部分がコンテンツを表示するのに適さないことがあります。これらは分離していることもあります。つまり、デバイスを開くと、2 つの物理ディスプレイが表示されます。
また、ヒンジが部分的に開いた状態でインナー ディスプレイを見ると、折りたたみの向きに応じてテーブルトップの形状(上の画像の右側に示される水平の折り目)とブックの形状(縦の折り目)で物理的な形状が異なる可能性があります。
詳しくは、折りたたみ形状とヒンジをご覧ください。
これらはすべて、折りたたみ式デバイスをサポートするアダプティブ レイアウトを実装するときに考慮すべき事項です。
適応型の情報を取得する
マテリアル 3 の adaptive
ライブラリを使用すると、アプリが実行されているウィンドウに関する情報に簡単にアクセスできます。
- このアーティファクトとそのバージョンのエントリをバージョン カタログ ファイルに追加します。
gradle/libs.versions.toml
[versions]
material3Adaptive = "1.0.0-beta01"
[libraries]
androidx-material3-adaptive = { module = "androidx.compose.material3.adaptive:adaptive", version.ref = "material3Adaptive" }
- アプリ モジュールのビルドファイルで、新しいライブラリ依存関係を追加し、Gradle 同期を実行します。
app/build.gradle.kts
dependencies {
implementation(libs.androidx.material3.adaptive)
}
これで、どのコンポーズ可能なスコープでも、currentWindowAdaptiveInfo()
を使用して、現在のウィンドウ サイズクラスや、デバイスがテーブルトップ形状などの折りたたみ式形状であるかどうかなどの情報を含む WindowAdaptiveInfo
オブジェクトを取得できます。
これは MainActivity
で今すぐお試しいただけます。
ReplyTheme
ブロック内のonCreate()
で、ウィンドウ アダプティブ情報を取得し、Text
コンポーザブルにサイズクラスを表示します。これはReplyApp()
要素の後に追加できます。
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ReplyTheme {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
ReplyApp(
replyHomeUIState = uiState,
onEmailClick = viewModel::setSelectedEmail
)
val adaptiveInfo = currentWindowAdaptiveInfo()
val sizeClassText =
"${adaptiveInfo.windowSizeClass.windowWidthSizeClass}\n" +
"${adaptiveInfo.windowSizeClass.windowHeightSizeClass}"
Text(
text = sizeClassText,
color = Color.Magenta,
modifier = Modifier.padding(
WindowInsets.safeDrawing.asPaddingValues()
)
)
}
}
}
アプリを実行すると、アプリのコンテンツに出力されたウィンドウ サイズクラスが表示されます。ウィンドウ アダプティブ情報では他にどのような情報が表示されているかも自由に検討してください。アプリのコンテンツが覆われており、次のステップでは不要なため、Text
は削除してかまいません。
4. ダイナミック ナビゲーション
次に、アプリを使いやすくするために、デバイスの状態とサイズの変化に合わせてアプリのナビゲーションを調整します。
ユーザーがスマートフォンを持っているとき、指は通常、画面の下部にあります。開いた状態の折りたたみ式デバイスやタブレットを持つとき、指は通常、側面の近くにあります。ユーザーは、極端な持ち方をしたり、持ち方を変えたりすることなく、アプリを操作したり操作を開始したりできる必要があります。
アプリを設計し、インタラクティブな UI 要素をレイアウト内のどこに配置するかを決定する際には、画面のさまざまな領域が人間工学的にどのような意味を持つかを考慮してください。
- デバイスを持っているときに手が届くのはどのような場所ですか?
- 指を伸ばすだけで到達できて不便と思われる分野はどれですか?
- 手の届かないところや、デバイスを持つ場所から遠くにあるところはどこですか?
ナビゲーションはユーザーが最初に操作する要素であり、クリティカル ユーザー ジャーニーに関連する重要なアクションが含まれているため、最もアクセスしやすい場所に配置する必要があります。マテリアル アダプティブ ライブラリには、デバイスのウィンドウ サイズクラスに応じて、ナビゲーションの実装に役立つコンポーネントがいくつか用意されています。
ボトム ナビゲーション
ボトム ナビゲーションは、自然な持ち方をした場合に親指がすべてのタッチポイントに簡単に届くので、コンパクト サイズに最適です。デバイスサイズがコンパクトの場合や、折りたたみ式デバイスの折りたたみ状態がコンパクトである場合に使用します。
ナビゲーション レール
中程度の幅のウィンドウ サイズの場合、親指がデバイスの側面に沿って自然に落ちるため、ナビゲーション レールは到達性に理想的です。ナビゲーション レールとナビゲーション ドロワーを組み合わせて、詳細情報を表示することもできます。
ナビゲーション ドロワー
ナビゲーション ドロワーを使用すると、ナビゲーション タブの詳細情報を簡単に確認できます。また、ナビゲーション ドロワーは、タブレットや大型デバイスを使用している場合に簡単にアクセスできます。ナビゲーション ドロワーには、モーダル ナビゲーション ドロワーと固定的なナビゲーション ドロワーの 2 種類があります。
モーダル ナビゲーション ドロワー
コンパクトから中程度のサイズのスマートフォンやタブレットでは、コンテンツ上でオーバーレイとして展開したり非表示にしたりできるため、モーダル ナビゲーション ドロワーを使用できます。ナビゲーション レールと組み合わせることもできます。
固定的なナビゲーション ドロワー
大型のタブレット、Chromebook、パソコンでは、固定ナビゲーションに固定的なナビゲーション ドロワーを使用できます。
ダイナミック ナビゲーションを実装する
次に、デバイスの状態とサイズの変化に応じて、ナビゲーションの種類を切り替えます。
現在、デバイスの状態に関係なく、画面コンテンツの下には常に NavigationBar
が表示されます。代わりに、マテリアル NavigationSuiteScaffold
コンポーネントを使用すると、現在のウィンドウ サイズクラスなどの情報に基づいて、異なるナビゲーション コンポーネントを自動的に切り替えることができます。
- Gradle 依存関係を追加して、このコンポーネントを取得するには、バージョン カタログとアプリのビルド スクリプトを更新してから、Gradle 同期を実行します。
gradle/libs.versions.toml
[versions]
material3AdaptiveNavSuite = "1.3.0-beta01"
[libraries]
androidx-material3-adaptive-navigation-suite = { module = "androidx.compose.material3:material3-adaptive-navigation-suite", version.ref = "material3AdaptiveNavSuite" }
app/build.gradle.kts
dependencies {
implementation(libs.androidx.material3.adaptive.navigation.suite)
}
ReplyApp.kt
でコンポーズ可能な関数ReplyNavigationWrapper()
を見つけ、Column
とその内容をNavigationSuiteScaffold
に置き換えます。
ReplyApp.kt
@Composable
private fun ReplyNavigationWrapperUI(
content: @Composable () -> Unit = {}
) {
var selectedDestination: ReplyDestination by remember {
mutableStateOf(ReplyDestination.Inbox)
}
NavigationSuiteScaffold(
navigationSuiteItems = {
ReplyDestination.entries.forEach {
item(
selected = it == selectedDestination,
onClick = { /*TODO update selection*/ },
icon = {
Icon(
imageVector = it.icon,
contentDescription = stringResource(it.labelRes)
)
},
label = {
Text(text = stringResource(it.labelRes))
},
)
}
}
) {
content()
}
}
navigationSuiteItems
引数は、LazyColumn
にアイテムを追加するのと同様に、item()
関数を使用してアイテムを追加できるブロックです。後置ラムダ内で、このコードは ReplyNavigationWrapperUI()
に引数として渡された content()
を呼び出します。
エミュレータでアプリを実行し、スマートフォン、折りたたみ式デバイス、タブレットの間でサイズを変えてみると、ナビゲーション バーがナビゲーション レールに変わり、そこから戻るのを確認できます。
横向きのタブレットなど、非常に幅の広いウィンドウでは、固定的なナビゲーション ドロワーを表示することをおすすめします。NavigationSuiteScaffold
は固定的なドロワーの表示をサポートしていますが、現在の WindowWidthSizeClass
値のいずれにも表示されません。ただし、わずかな変更で変更できます。
NavigationSuiteScaffold
を呼び出す直前に、次のコードを追加します。
ReplyApp.kt
@Composable
private fun ReplyNavigationWrapperUI(
content: @Composable () -> Unit = {}
) {
var selectedDestination: ReplyDestination by remember {
mutableStateOf(ReplyDestination.Inbox)
}
val windowSize = with(LocalDensity.current) {
currentWindowSize().toSize().toDpSize()
}
val layoutType = if (windowSize.width >= 1200.dp) {
NavigationSuiteType.NavigationDrawer
} else {
NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(
currentWindowAdaptiveInfo()
)
}
NavigationSuiteScaffold(
layoutType = layoutType,
...
) {
content()
}
}
このコードは、まずウィンドウ サイズを取得し、currentWindowSize()
と LocalDensity.current
を使用して DP 単位に変換してから、ウィンドウの幅を比較してナビゲーション UI のレイアウト タイプを決定します。ウィンドウの幅が 1200.dp
以上の場合は、NavigationSuiteType.NavigationDrawer
を使用します。それ以外の場合は、デフォルトの計算にフォールバックします。
サイズ変更可能なエミュレータでアプリを再度実行し、さまざまなタイプを試すと、画面構成が変更されたり、折りたたみ式デバイスを開いたりするたびに、ナビゲーションがそのサイズに適したタイプに変わるのがわかります。
これで、さまざまなタイプのウィンドウ サイズと状態をサポートする各種のナビゲーションについて学習しました。
次のセクションでは、同じリストアイテムを端から端まで引き伸ばさずに、残りの画面領域を活用する方法について説明します。
5. 画面スペースの使用
アプリを実行しているのが小さなタブレット、広げたデバイス、大型タブレットのどれであっても、画面は引き伸ばされ、残りのスペースが使われます。このアプリのように、その画面スペースを活用して、同じページにメールとスレッドを表示するなど、より多くの情報を表示できるようにしてはどうでしょうか。
マテリアル 3 では 3 つの正規レイアウトが定義されており、それぞれにコンパクト、中程度、拡大のウィンドウ サイズクラスの設定があります。このユースケースにはリストの詳細の正規レイアウトが最適で、Compose で ListDetailPaneScaffold
として利用できます。
- このコンポーネントを取得するには、次の依存関係を追加し、Gradle 同期を実行します。
gradle/libs.versions.toml
[libraries]
androidx-material3-adaptive-layout = { module = "androidx.compose.material3.adaptive:adaptive-layout", version.ref = "material3Adaptive" }
androidx-material3-adaptive-navigation = { module = "androidx.compose.material3.adaptive:adaptive-navigation", version.ref = "material3Adaptive" }
app/build.gradle.kts
dependencies {
implementation(libs.androidx.material3.adaptive.layout)
implementation(libs.androidx.material3.adaptive.navigation)
}
ReplyApp.kt
でコンポーズ可能な関数ReplyAppContent()
を見つけます。現在、これはReplyListPane()
を呼び出してリストペインのみを表示します。次のコードを挿入して、この実装をListDetailPaneScaffold
に置き換えます。これは試験運用版 API であるため、ReplyAppContent()
関数に@OptIn
アノテーションも追加します。
ReplyApp.kt
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ReplyAppContent(
replyHomeUIState: ReplyHomeUIState,
onEmailClick: (Email) -> Unit,
) {
val navigator = rememberListDetailPaneScaffoldNavigator<Long>()
ListDetailPaneScaffold(
directive = navigator.scaffoldDirective,
value = navigator.scaffoldValue,
listPane = {
ReplyListPane(replyHomeUIState, onEmailClick)
},
detailPane = {
ReplyDetailPane(replyHomeUIState.emails.first())
}
)
}
このコードは、まず rememberListDetailPaneNavigator
を使用してナビゲータを作成します。ナビゲータでは、表示するペインと、そのペインで表示するコンテンツを制御できます。これについては後で説明します。
ListDetailPaneScaffold
は、ウィンドウ幅サイズクラスが展開されると 2 つのペインを表示します。それ以外の場合は、scaffold ディレクティブと scaffold 値の 2 つのパラメータに指定された値に基づいて、一方のペインまたはもう一方のペインを表示します。このコードは、デフォルトの動作を得るために、scaffold ディレクティブと、ナビゲータによって提供される scaffold 値を使用します。
残りの必須パラメータは、ペインのコンポーズ可能なラムダです。ReplyListPane()
と ReplyDetailPane()
(ReplyListContent.kt
にあります)は、それぞれリストペインと詳細ペインの役割を埋めるために使用されます。ReplyDetailPane()
はメールの引数を想定しているため、今のところ、このコードは ReplyHomeUIState
のメールリストの最初のメールを使用します。
アプリを実行し、エミュレータ ビューを折りたたみ式デバイスまたはタブレットに切り替えて(向きの変更が必要になることもあります)、2 ペイン レイアウトを確認します。見た目が以前よりかなり良くなりました。
次に、この画面の動作に対処しましょう。ユーザーがリストペインでメールをタップすると、すべての返信とともに詳細ペインに表示されます。現時点では、どのメールが選択されたかは記録されず、アイテムをタップしても何も起こりません。この情報を保持するのに最適な場所は、ReplyHomeUIState
の残りの UI 状態です。
ReplyHomeViewModel.kt
を開き、ReplyHomeUIState
データクラスを見つけます。選択したメールのプロパティを追加します。デフォルト値はnull
です。
ReplyHomeViewModel.kt
data class ReplyHomeUIState(
val emails : List<Email> = emptyList(),
val selectedEmail: Email? = null,
val loading: Boolean = false,
val error: String? = null
)
- 同じファイル内の
ReplyHomeViewModel
には、ユーザーがリストアイテムをタップしたときに呼び出されるsetSelectedEmail()
関数があります。UI 状態をコピーして、選択したメールを記録するように、この関数を変更します。
ReplyHomeViewModel.kt
fun setSelectedEmail(email: Email) {
_uiState.update {
it.copy(selectedEmail = email)
}
}
考慮すべきことは、ユーザーがアイテムをタップし、選択されたメールアドレスが null
になる前に起こっていることです。詳細ペインには何を表示すればよいですか。この処理には、デフォルトでリストの最初のアイテムを表示するなど、複数の方法があります。
- 同じファイルで、
observeEmails()
関数を変更します。メールのリストが読み込まれたときに、以前の UI の状態にメールが選択されていない場合は、最初の項目に設定します。
ReplyHomeViewModel.kt
private fun observeEmails() {
viewModelScope.launch {
emailsRepository.getAllEmails()
.catch { ex ->
_uiState.value = ReplyHomeUIState(error = ex.message)
}
.collect { emails ->
val currentSelection = _uiState.value.selectedEmail
_uiState.value = ReplyHomeUIState(
emails = emails,
selectedEmail = currentSelection ?: emails.first()
)
}
}
}
ReplyApp.kt
に戻り、選択したメールアドレス(利用可能な場合)を使用して、詳細ペインのコンテンツを入力します。
ReplyApp.kt
ListDetailPaneScaffold(
// ...
detailPane = {
if (replyHomeUIState.selectedEmail != null) {
ReplyDetailPane(replyHomeUIState.selectedEmail)
}
}
)
アプリを再度実行し、エミュレータをタブレット サイズに切り替えると、リストアイテムをタップすると詳細ペインのコンテンツが更新されることがわかります。
これは両方のペインが表示されている場合にはうまく機能しますが、ウィンドウに 1 つのペインを表示するスペースしかない場合は、アイテムをタップしても何も起こらないように見えます。エミュレータ ビューをスマートフォンや折りたたみ式デバイス(縦向き)に切り替えると、アイテムをタップしてもリストペインしか表示されないことがわかります。これは、選択したメールアドレスが更新されても、これらの構成では ListDetailPaneScaffold
がリストペインにフォーカスを保持しているためです。
- これを修正するには、
ReplyListPane
に渡されるラムダとして次のコードを挿入します。
ReplyApp.kt
ListDetailPaneScaffold(
// ...
listPane = {
ReplyListPane(
replyHomeUIState = replyHomeUIState,
onEmailClick = { email ->
onEmailClick(email)
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, email.id)
}
)
},
// ...
)
このラムダは、前に作成したナビゲータを使用して、アイテムがクリックされたときの動作を追加します。この関数に渡された元のラムダを呼び出し、表示するペインを指定して navigator.navigateTo()
も呼び出します。スキャフォールドの各ペインにはロールが関連付けられています。詳細ペインでは ListDetailPaneScaffoldRole.Detail
です。小さいウィンドウでは、アプリが前に移動したように見えます。
また、ユーザーが詳細ペインの [戻る] ボタンを押したときの動作も処理する必要があります。この動作は、表示されるペインが 1 つか 2 つかによって異なります。
- 次のコードを追加して、「戻る」ナビゲーションをサポートします。
ReplyApp.kt
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
@Composable
fun ReplyAppContent(
replyHomeUIState: ReplyHomeUIState,
onEmailClick: (Email) -> Unit,
) {
val navigator = rememberListDetailPaneScaffoldNavigator<Long>()
BackHandler(navigator.canNavigateBack()) {
navigator.navigateBack()
}
ListDetailPaneScaffold(
directive = navigator.scaffoldDirective,
value = navigator.scaffoldValue,
listPane = {
AnimatedPane {
ReplyListPane(
replyHomeUIState = replyHomeUIState,
onEmailClick = { email ->
onEmailClick(email)
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, email.id)
}
)
}
},
detailPane = {
AnimatedPane {
if (replyHomeUIState.selectedEmail != null) {
ReplyDetailPane(replyHomeUIState.selectedEmail)
}
}
}
)
}
ナビゲータは、ListDetailPaneScaffold
の完全な状態、戻るナビゲーションの可否、これらすべてのシナリオでの対処方法を認識しています。このコードは、ナビゲータが戻ることができ、ラムダ内で navigateBack()
を呼び出すたびに有効になる BackHandler
を作成します。また、ペイン間の遷移をよりスムーズにするために、各ペインを AnimatedPane()
コンポーザブルでラップします。
サイズ変更可能なエミュレータで、さまざまなタイプのデバイスでアプリを再度実行すると、画面構成が変更されたり、折りたたみ式デバイスを開いたりするたびに、デバイスの状態の変化に応じてナビゲーションと画面コンテンツが動的に変化することがわかります。また、リストペインでメールをタップして、レイアウトがさまざまな画面でどのように動作するか(両方のペインを横に並べて表示したり、アニメーション間でスムーズに表示したり)を試してみてください。
これで、アプリをあらゆる種類のデバイスとサイズに自動適応させることができました。折りたたみ式デバイス、タブレット、その他のモバイル デバイスでアプリを実行してみましょう。
6. 完了
これで、この Codelab は終了です。Jetpack Compose でアプリをアダプティブにする方法を学びました。
デバイスのサイズと折りたたみ状態をチェックし、それに応じてアプリの UI、ナビゲーション、その他の機能を更新する方法を学習しました。また、適応性によって到達性が向上し、ユーザー エクスペリエンスが向上することも学びました。
次のステップ
Compose パスウェイにある他の Codelab をご確認ください。
サンプルアプリ
- Compose サンプルは、Codelab で説明したベスト プラクティスを組み込んだ多くのアプリのコレクションです。