アプリを折りたたみ対応にする

折りたたみ式デバイスでは、開いた状態の大型ディスプレイと独自の折りたたみ状態により、新しいユーザー エクスペリエンスを実現します。Jetpack Compose でアプリを折りたたみ対応にするには、 Compose Material 3 Adaptive ライブラリを使用します。このライブラリは、折りたたみ式 デバイスの折り目、ヒンジ、デバイスの形状などのウィンドウ機能用の API を提供します。アプリを折りたたみ対応にすると、レイアウトを調整して、重要なコンテンツが折り目またはヒンジの領域に配置されることを回避したり、折り目またはヒンジを自然な区切り要素として使用したりすることができます。

デバイスがテーブルトップ形状やブック形状などの構成をサポートしているかどうかを把握することで、さまざまなレイアウトのサポートや特定の機能の提供に関する判断に役立てることができます。

ウィンドウ情報

Jetpack Compose でウィンドウの折りたたみ情報を確認するには、collectFoldingFeaturesAsState() コンポーズ可能な 関数を使用します。 collectFoldingFeaturesAsState() は、現在のウィンドウの折りたたみ機能を WindowInfoTracker から収集し、State に格納します。これには、FoldingFeature オブジェクトのリストが含まれます。

collectFoldingFeaturesAsState() は Compose State を返すため、 コンポーズ可能な関数がデバイスの折りたたみ状態や形状が 変更されるたびに、手動でライフサイクルを管理したりフローを収集したりすることなく、自動的に再コンポーズされます。

@Composable
fun FoldAwareScreen() {
    val foldingFeatures by collectFoldingFeaturesAsState()

    // Access folding features for the current window.
    val foldFeature = foldingFeatures.firstOrNull()
    if (foldFeature != null) {
        // Adapt layout based on the fold feature.
    }
}

折りたたみ式ディスプレイの機能

collectFoldingFeaturesAsState()DisplayFeature のサブタイプ)から返される FoldingFeature 要素のリストには、次のような折りたたみ式ディスプレイに関する情報が含まれています。

  • state:デバイスの折りたたみ状態(FLAT または HALF_OPENED

  • orientation:折り目またはヒンジの向き(HORIZONTAL または VERTICAL

  • occlusionType: 折り目またはヒンジがディスプレイを隠しているかどうか( NONE または FULL

  • isSeparating: 折り目またはヒンジが 2 つの論理ディスプレイ領域を生成するかどうか(true または false)

HALF_OPENED 状態の折りたたみ式デバイスは、画面が 2 つのディスプレイ領域に分割されているため、常に isSeparating を true として報告します。また、デュアル スクリーン デバイスでは、アプリが両方の画面にまたがっている場合、isSeparating は常に true になります。

FoldingFeature bounds プロパティ(DisplayFeatureから継承される)は、折り目やヒンジなどの折りたたみ機能の境界四角形を表します。この境界を使用して、折りたたみ機能からの相対位置に画面上の要素を配置できます。

@Composable
fun FoldFeatureDemo() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    if (foldFeature != null) {
        val isSeparating = foldFeature.isSeparating
        val occlusionType = foldFeature.occlusionType
        val bounds = foldFeature.bounds
        // Use bounds and properties to position content.
    }
}

テーブルトップ形状

FoldingFeature オブジェクトに含まれる情報を使用して、アプリはテーブルトップなどの形状に対応することができます。テーブルトップとは、スマートフォンが平面に置かれ、ヒンジが水平位置で、折りたたみ式画面が半分開いた状態です。

テーブルトップ形状では、スマートフォンを手に持たずに簡単に操作できます。テーブルトップ形状は、メディアの再生、写真の撮影、ビデオ通話に最適です。

画面の縦向きの垂直部分で動画を再生し、下部の水平部分で再生コントロールを表示する、テーブルトップ姿勢の動画プレーヤー アプリ。
図 1.テーブルトップ形状の動画プレーヤー アプリ。画面の縦向きの部分に動画、横向きの部分に再生コントロールが表示されます。

collectFoldingFeaturesAsState()FoldingFeature.StateFoldingFeature.Orientation を使用して、デバイスがテーブルトップ ポスチャーかどうかを判断します。

@Composable
fun TabletopContent() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    val isTableTopPosture = foldFeature != null &&
        foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL

    if (isTableTopPosture) {
        // Tabletop layout: separate content and controls across the fold.
    } else {
        // Standard layout.
    }
}

または、ウィンドウがテーブルトップ形状かどうかを 判断するには、Posture から返される currentWindowAdaptiveInfoV2()を確認することもできます。

val adaptiveInfo = currentWindowAdaptiveInfoV2()
val isTabletop = adaptiveInfo.windowPosture.isTabletop

デバイスがテーブルトップ形状であることを確認したら、それに応じてアプリのレイアウトを更新します。メディアアプリの場合は、通常、ハンズフリーで視聴できるように、スクロールせずに見える範囲に再生を配置し、そのすぐ下にコントロールと補足コンテンツを配置します。

ブック形状

折りたたみ式ならではのもう 1 つの機能としてブック形状があります。ブック形状とは、デバイスが半分開き、ヒンジが垂直の状態です。ブック形状は電子書籍を読むのに最適です。大きい折りたたみ式画面を製本された本のように開いて 2 ページ レイアウトにするブック形状では、本物の本を読むようなエクスペリエンスを提供できます。

また、写真撮影に使用すれば、ハンズフリーで写真を撮る際に異なるアスペクト比でキャプチャすることもできます。

ブック形状の実装方法はテーブルトップ形状と同じです。折りたたみ機能の向きが水平ではなく垂直であることを確認します。

@Composable
fun BookContent() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    val isBookPosture = foldFeature != null &&
        foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.VERTICAL

    if (isBookPosture) {
        // Book posture layout: two-page layout across the vertical fold.
    } else {
        // Standard single-page layout.
    }
}

ウィンドウ サイズの変更

アプリのディスプレイ領域は、デバイス設定の変更に伴って変化する可能性があります。これには、デバイスが折りたたまれたとき、広げられたとき、回転されたとき、マルチウィンドウ モードでサイズが変更されたときなどがあります。

現在のウィンドウ サイズクラスを取得し、Jetpack Compose でサイズの変更に対応するには、currentWindowAdaptiveInfoV2() コンポーズ可能な関数を Compose Material 3 Adaptive libraryから使用します。currentWindowAdaptiveInfoV2() は、現在のウィンドウのWindowAdaptiveInfo(デフォルトで大と 特大のブレークポイントをサポート)とデバイスの windowPostureを提供するWindowSizeClassインスタンスを返します。

@Composable
fun AdaptiveApp() {
    val adaptiveInfo = currentWindowAdaptiveInfoV2()
    val windowSizeClass = adaptiveInfo.windowSizeClass

    when {
        windowSizeClass.isWidthAtLeastBreakpoint(
            WIDTH_DP_EXPANDED_LOWER_BOUND
        ) -> {
            // Expanded layout
        }
        windowSizeClass.isWidthAtLeastBreakpoint(
            WIDTH_DP_MEDIUM_LOWER_BOUND
        ) -> {
            // Medium layout
        }
        else -> {
            // Compact layout
        }
    }
}

ウィンドウ サイズクラスを使用するをご覧ください。

参考情報

折りたたみ対応レイアウトと折りたたみ式デバイスについて詳しくは、次のリソースをご覧ください。

サンプル

Codelab