앱에서 접힌 상태 인식

펼친 상태의 대형 디스플레이와 고유한 접힌 상태는 폴더블 기기에서 새로운 사용자 환경을 제공합니다. Jetpack Compose에서 앱이 접힌 상태를 인식하도록 하려면 접힘, 힌지, 기기 상태와 같은 폴더블 기기 창 기능에 API를 제공하는 Compose Material 3 Adaptive 라이브러리를 사용합니다. 앱이 접힌 상태를 인식하는 경우 접힘 또는 힌지 영역에 중요한 콘텐츠를 배치하지 않고 접힘과 힌지를 자연스러운 구분선으로 사용하도록 레이아웃을 조정할 수 있습니다.

기기가 탁자 모드 또는 책 모드와 같은 구성을 지원하는지 이해하면 다양한 레이아웃을 지원하거나 특정 기능을 제공하는 것에 관한 결정을 내리는 데 도움이 될 수 있습니다.

창 정보

Jetpack Compose에서 collectFoldingFeaturesAsState() 구성 가능한 함수를 사용하여 창 접기 정보를 관찰합니다. collectFoldingFeaturesAsState()는 현재 창 접기 기능 WindowInfoTracker에서 FoldingFeature`FoldingFeature` 객체 목록이 포함된 Compose State로 수집합니다.

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.
    }
}

폴더블 디스플레이 기능

FoldingFeature 요소 목록 (DisplayFeature의 하위 유형) 은 다음과 같은 속성을 비롯하여 폴더블 디스플레이에 관한 정보를 제공합니다.collectFoldingFeaturesAsState()

  • state: 기기의 접힌 상태(FLAT 또는 HALF_OPENED)

  • orientation: 접힘 또는 힌지의 방향, HORIZONTAL 또는 VERTICAL

  • occlusionType: 접힘 또는 힌지가 디스플레이의 일부를 가리는지 여부, NONE 또는 FULL

  • isSeparating: 접힘 또는 힌지가 두 개의 논리 디스플레이 영역을 생성하는지 여부(true 또는 false)

HALF_OPENED인 폴더블 기기는 화면이 두 개의 디스플레이 영역으로 분리되므로 항상 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

기기가 탁자 모드임을 알면 그에 따라 앱 레이아웃을 업데이트합니다. 미디어 앱의 경우 일반적으로 스크롤 없이 볼 수 있는 부분에 재생을 배치하고, 핸즈프리 보기 또는 청취 환경을 위해 위치 지정 컨트롤과 보조 콘텐츠를 바로 아래에 배치하는 것을 의미합니다.

책 모드

또 다른 고유한 폴더블 기능은 기기가 반쯤 열려 있고 힌지가 수직인 책 모드입니다. 책 모드는 eBook을 읽을 때 유용합니다. 책 모드는 대형 폴더블 화면에 열린 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 라이브러리 currentWindowAdaptiveInfoV2() 는 기본적으로 대형 및 초대형 중단점을 지원하는 현재 창의 WindowSizeClass와 기기의 windowPosture를 제공하는 WindowAdaptiveInfo 인스턴스를 반환합니다.

@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