CoordinatorLayout을 Compose로 이전

CoordinatorLayout는 복잡하고 겹치는 중첩된 레이아웃을 지원하는 ViewGroup입니다. 특정 Material Design을 사용 설정하는 컨테이너로 사용됩니다. 확장/축소 툴바 및 하단 시트 등의 상호작용을 지원합니다. 확인할 수 있습니다

Compose에서 CoordinatorLayout와 가장 유사한 것은 Scaffold입니다. Scaffold는 Material 결합을 위한 콘텐츠 슬롯을 제공합니다. 일반적인 화면 패턴 및 상호작용의 구성요소입니다. 이 페이지에서는 CoordinatorLayout 구현을 이전하여 다음 위치에서 Scaffold를 사용할 수 있습니다. 편지쓰기를 클릭합니다.

이전 단계

CoordinatorLayoutScaffold로 이전하려면 다음 단계를 따르세요.

  1. 아래 스니펫에서 CoordinatorLayout에는 AppBarLayout 이 클래스는 ToolBar, ViewPager, FloatingActionButton를 포함합니다. UI 계층 구조에서 CoordinatorLayout 및 그 하위 요소를 주석 처리하고 이를 대체할 ComposeView를 추가합니다.

    <!--  <androidx.coordinatorlayout.widget.CoordinatorLayout-->
    <!--      android:id="@+id/coordinator_layout"-->
    <!--      android:layout_width="match_parent"-->
    <!--      android:layout_height="match_parent"-->
    <!--      android:fitsSystemWindows="true">-->
    
    <!--    <androidx.compose.ui.platform.ComposeView-->
    <!--        android:id="@+id/compose_view"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="match_parent"-->
    <!--        app:layout_behavior="@string/appbar_scrolling_view_behavior" />-->
    
    <!--    <com.google.android.material.appbar.AppBarLayout-->
    <!--        android:id="@+id/app_bar_layout"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="wrap_content"-->
    <!--        android:fitsSystemWindows="true"-->
    <!--        android:theme="@style/Theme.Sunflower.AppBarOverlay">-->
    
        <!-- AppBarLayout contents here -->
    
    <!--    </com.google.android.material.appbar.AppBarLayout>-->
    
    <!--  </androidx.coordinatorlayout.widget.CoordinatorLayout>-->
    
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
  2. Fragment 또는 Activity에서 개발자가 제공한 ComposeView의 참조를 가져옵니다. 방금 추가하고 setContent 메서드를 호출합니다. 메서드의 본문에서 Scaffold를 콘텐츠로 설정합니다.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            // Scaffold contents
            // ...
        }
    }

  3. Scaffold의 콘텐츠에 화면의 기본 콘텐츠를 추가합니다. 위 XML의 기본 콘텐츠는 ViewPager2이므로 HorizontalPager: Compose와 동등한 것입니다. content 람다 Scaffold의 인스턴스도 다음과 같아야 하는 PaddingValues의 인스턴스를 받습니다. 콘텐츠 루트에 적용됩니다. Modifier.padding를 사용하여 동일하게 PaddingValuesHorizontalPager로 전송합니다.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. Scaffold에서 제공하는 다른 콘텐츠 슬롯을 사용하여 더 많은 화면 요소를 추가합니다. 나머지 하위 뷰를 이전할 수 있습니다. topBar 슬롯을 사용하여 TopAppBar를 추가하고 floatingActionButton 슬롯을 사용하여 FloatingActionButton를 제공할 수 있습니다.

    composeView.setContent {
        Scaffold(
            Modifier.fillMaxSize(),
            topBar = {
                TopAppBar(
                    title = {
                        Text("My App")
                    }
                )
            },
            floatingActionButton = {
                FloatingActionButton(
                    onClick = { /* Handle click */ }
                ) {
                    Icon(
                        Icons.Filled.Add,
                        contentDescription = "Add Button"
                    )
                }
            }
        ) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

일반적인 사용 사례

툴바 접기 및 펼치기

뷰 시스템에서 CoordinatorLayout를 사용하여 툴바를 접고 펼치려면 AppBarLayout를 툴바의 컨테이너로 사용합니다. 그런 다음 연결된 스크롤 가능한 뷰(예: RecyclerView 또는 NestedScrollView)의 XML에서 layout_behavior를 통해 Behavior를 지정하여 스크롤할 때 툴바가 접히거나 펼쳐지는 방식을 선언할 수 있습니다.

Compose에서는 TopAppBarScrollBehavior를 통해 유사한 효과를 얻을 수 있습니다. 예를 들어 접기/펼치기를 구현하려면 위로 스크롤할 때 툴바가 표시되도록 하려면 다음 단계를 따르세요.

  1. TopAppBarDefaults.enterAlwaysScrollBehavior()를 호출하여 TopAppBarScrollBehavior를 만듭니다.
  2. 생성된 TopAppBarScrollBehaviorTopAppBar에 제공합니다.
  3. 다음에서 Modifier.nestedScroll를 통해 NestedScrollConnection를 연결합니다. Scaffold를 사용하면 Scaffold가 중첩된 스크롤 이벤트를 스크롤 가능한 콘텐츠가 위/아래로 스크롤됨 이렇게 하면 콘텐츠가 스크롤될 때 포함된 앱 바가 적절하게 접히거나 펼쳐질 수 있습니다.

    // 1. Create the TopAppBarScrollBehavior
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text("My App")
                },
                // 2. Provide scrollBehavior to TopAppBar
                scrollBehavior = scrollBehavior
            )
        },
        // 3. Connect the scrollBehavior.nestedScrollConnection to the Scaffold
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(scrollBehavior.nestedScrollConnection)
    ) { contentPadding ->
        /* Contents */
        // ...
    }

을 확인해 보세요.

접기/펼치기 스크롤 효과 맞춤설정

enterAlwaysScrollBehavior에 여러 매개변수를 제공하여 접기/펼치기 애니메이션 효과를 맞춤설정할 수 있습니다. TopAppBarDefaults는 콘텐츠가 완전히 아래로 스크롤될 때만 앱 바를 확장하는 exitUntilCollapsedScrollBehavior와 같은 다른 TopAppBarScrollBehavior도 제공합니다.

완전한 맞춤 효과 (예: 시차 효과)를 만들려면 다음 작업을 수행합니다. 또한 자체 NestedScrollConnection를 만들고 다음과 같이 수동으로 툴바를 오프셋합니다. 콘텐츠가 스크롤됩니다. 자세한 내용은 AOSP의 중첩 스크롤 샘플을 참고하세요. 코드 예제를 참조하세요.

뷰를 사용하면 탐색 창을 구현할 때 DrawerLayout를 루트 뷰로 사용합니다. 따라서 CoordinatorLayoutDrawerLayout의 하위 뷰입니다. DrawerLayout에는 드로어에 탐색 옵션을 표시하는 NavigationView와 같은 다른 하위 뷰도 포함되어 있습니다.

Compose에서는 ModalNavigationDrawer 컴포저블 함수. ModalNavigationDrawerdrawerContent 창 슬롯 및 content 화면 있습니다.

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    Scaffold(Modifier.fillMaxSize()) { contentPadding ->
        // Scaffold content
        // ...
    }
}

자세한 내용은 드로어를 참고하세요.

스낵바

ScaffoldSnackbarHost를 허용할 수 있는 snackbarHost 슬롯을 제공합니다. 컴포저블을 사용하여 Snackbar를 표시합니다.

val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState)
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            text = { Text("Show snackbar") },
            icon = { Icon(Icons.Filled.Image, contentDescription = "") },
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("Snackbar")
                }
            }
        )
    }
) { contentPadding ->
    // Screen content
    // ...
}

자세한 내용은 스낵바를 참고하세요.

자세히 알아보기

CoordinatorLayout를 Compose로 이전하는 방법에 관한 자세한 내용은 다음을 참고하세요. 다음 리소스를 참고하세요.