Jetpack Compose를 사용하면 앱의 UI를 훨씬 쉽게 디자인하고 빌드할 수 있습니다. Compose는 다음을 통해 상태를 UI 요소로 변환합니다.
- 요소 구성
- 요소 레이아웃
- 요소 그림
이 문서에서는 요소의 레이아웃을 중심으로, UI 요소를 간단히 배치하는 데 유용한 Compose의 일부 기본 구성요소를 설명합니다.
Compose의 레이아웃 목표
Jetpack Compose의 레이아웃 시스템 구현에는 두 가지 주요 목표가 있습니다.
구성 가능한 함수 기본사항
구성 가능한 함수는 Compose의 기본 구성요소입니다. 구성 가능한 함수는 UI의 일부를 설명하는 Unit
을 내보내는 함수입니다. 이 함수는 몇 가지 입력을 받아서 화면에 표시되는 내용을 생성합니다. 컴포저블에 관한 자세한 내용은 Compose 멘탈 모델 문서를 살펴보세요.
구성 가능한 함수는 여러 UI 요소를 내보낼 수 있습니다. 그러나 개발자가 UI 요소를 어떻게 정렬해야 하는지에 관한 가이드를 제공하지 않으면 Compose는 개발자가 원하지 않는 방식으로 요소를 정렬할 수 있습니다. 예를 들어 다음 코드는 텍스트 요소 두 개를 생성합니다.
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
원하는 정렬 방식에 관한 가이드가 없으면 Compose는 텍스트 요소를 서로 겹치게 표시하므로 텍스트를 읽을 수 없게 됩니다.
Compose는 UI 요소를 정렬하는 데 도움이 되도록 즉시 사용 가능한 레이아웃 컬렉션을 제공하므로 이를 사용하면 더욱 전문적인 고유한 레이아웃을 쉽게 정의할 수 있습니다.
표준 레이아웃 구성요소
많은 경우에 Compose의 표준 레이아웃 요소를 사용할 수 있습니다.
Column
을 사용하여 항목을 화면에 세로로 배치합니다.
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
마찬가지로 Row
를 사용하여 항목을 화면에 가로로 배치합니다. Column
과 Row
는 모두 포함된 요소의 정렬 구성을 지원합니다.
@Composable fun ArtistCardRow(artist: Artist) { Row(verticalAlignment = Alignment.CenterVertically) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { Text(artist.name) Text(artist.lastSeenOnline) } } }
Box
를 사용하여 요소를 다른 요소 위에 놓습니다. Box
는 포함된 요소의 특정 정렬 구성도 지원합니다.
@Composable fun ArtistAvatar(artist: Artist) { Box { Image(bitmap = artist.image, contentDescription = "Artist image") Icon(Icons.Filled.Check, contentDescription = "Check mark") } }
흔히 이러한 구성요소만 있으면 됩니다. 자체 구성 가능한 함수를 작성하여 이러한 여러 레이아웃을 앱에 적합한 더욱 정교한 레이아웃으로 결합할 수 있습니다.
Row
내에서 하위 요소의 위치를 설정하려면 horizontalArrangement
및 verticalAlignment
인수를 설정하세요. Column
의 경우 verticalArrangement
및 horizontalAlignment
인수를 설정합니다.
@Composable fun ArtistCardArrangement(artist: Artist) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { /*...*/ } } }
레이아웃 모델
레이아웃 모델에서 UI 트리는 단일 패스로 배치됩니다. 각 노드는 먼저 자체 측정을 요청받고 하위 요소를 반복적으로 측정하여 크기 제약 조건을 트리 아래 하위 요소로 전달합니다. 그러면 리프 노드가 크기 지정 및 배치되고 확인된 크기 및 배치 안내는 다시 트리 위로 전달됩니다.
간단히 말해 상위 요소는 하위 요소보다 먼저 측정되지만 크기와 위치는 하위 요소 다음에 지정됩니다.
다음 SearchResult
함수를 살펴보세요.
@Composable fun SearchResult() { Row { Image( // ... ) Column { Text( // ... ) Text( // ... ) } } }
이 함수는 다음과 같은 UI 트리를 생성합니다.
SearchResult
Row
Image
Column
Text
Text
SearchResult
예에서는 다음 순서에 따라 UI 트리가 레이아웃됩니다.
- 루트 노드
Row
에 측정을 요청합니다. - 루트 노드
Row
는 첫 번째 하위 요소Image
에 측정을 요청합니다. Image
는 리프 노드(하위 요소가 없음)이므로 크기를 보고하고 배치 안내를 반환합니다.- 루트 노드
Row
는 두 번째 하위 요소Column
에 측정을 요청합니다. Column
노드는 첫 번째Text
하위 요소에 측정을 요청합니다.- 첫 번째
Text
노드는 리프 노드이므로 크기를 보고하고 배치 안내를 반환합니다. Column
노드는 두 번째Text
하위 요소에 측정을 요청합니다.- 두 번째
Text
노드는 리프 노드이므로 크기를 보고하고 배치 안내를 반환합니다. - 이제
Column
노드가 하위 요소를 측정하여 크기를 지정하고 배치했으므로 자체 크기와 배치를 결정할 수 있습니다. - 이제 루트 노드
Row
가 하위 요소를 측정하여 크기를 지정하고 배치했으므로 자체 크기와 배치를 결정할 수 있습니다.
성능
Compose는 하위 요소를 한 번만 측정하여 높은 성능을 발휘합니다. 단일 패스 측정은 성능 측면에서 효율적이므로 Compose가 깊은 UI 트리를 효율적으로 처리할 수 있습니다. 요소가 하위 요소를 두 번 측정한 후 이 하위 요소가 각각의 자체 하위 요소를 두 번 측정하는 방식은 전체 UI를 배치하려는 한 번의 시도에서 많은 작업을 실행해야 하므로 앱의 성능을 유지하기가 어렵습니다.
어떤 이유로든 레이아웃에 여러 측정이 필요하면 Compose는 내장 측정 기능이라는 특수한 시스템을 제공합니다. 이 기능에 관한 자세한 내용은 Compose 레이아웃의 내장 기능 측정을 참고하세요.
측정과 배치는 레이아웃 패스의 별개 하위 단계이므로, 항목의 측정이 아닌 배치에만 영향을 미치는 모든 변경사항은 별도로 실행할 수 있습니다.
레이아웃에서 수정자 사용
Compose 수정자에서 설명한 대로 수정자를 사용하여 컴포저블을 장식하거나 강화할 수 있습니다. 수정자는 레이아웃을 맞춤설정하는 데 필수적입니다. 예를 들어 여기서는 여러 수정자를 연결하여 ArtistCard
를 맞춤설정합니다.
@Composable fun ArtistCardModifiers( artist: Artist, onClick: () -> Unit ) { val padding = 16.dp Column( Modifier .clickable(onClick = onClick) .padding(padding) .fillMaxWidth() ) { Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ } Spacer(Modifier.size(padding)) Card( elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), ) { /*...*/ } } }
위의 코드에서 다양한 수정자 함수가 함께 사용된 것을 확인할 수 있습니다.
clickable
: 컴포저블이 사용자 입력에 반응하도록 설정하고 물결 효과를 표시합니다.padding
: 요소 주위에 공간을 배치합니다.fillMaxWidth
: 컴포저블이 상위 요소로부터 부여받은 최대 너비를 채우도록 합니다.size()
: 요소의 기본 너비 및 높이를 지정합니다.
스크롤 가능한 레이아웃
Compose 동작 문서에서 스크롤 가능한 레이아웃에 관해 자세히 알아보세요.
목록과 지연 목록은 Compose 목록 문서를 참고하세요.
반응형 레이아웃
레이아웃은 여러 화면 방향과 폼 팩터 크기를 고려하여 디자인해야 합니다. Compose에서 제공하는 즉시 사용 가능한 몇 가지 메커니즘으로 컴포저블 레이아웃을 다양한 화면 구성에 따라 쉽게 조정할 수 있습니다.
제약 조건
상위 요소의 제약 조건을 파악하고 그에 따라 레이아웃을 디자인하려면 BoxWithConstraints
를 사용하면 됩니다. 측정 제약 조건은 콘텐츠 람다의 범위에서 확인할 수 있습니다. 이 측정 제약 조건을 사용하여 다양한 화면 구성에 따라 다양한 레이아웃을 구성할 수 있습니다.
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
슬롯 기반 레이아웃
Compose는 UI를 쉽게 빌드할 수 있도록 머티리얼 디자인 및 Android 스튜디오에서 Compose 프로젝트를 만들 때 포함되는 androidx.compose.material:material
종속 항목을 기반으로 한 다양한 컴포저블을 제공합니다. Drawer
, FloatingActionButton
및 TopAppBar
와 같은 요소가 모두 제공됩니다.
머티리얼 구성요소는 Compose가 컴포저블 위에 맞춤설정 레이어를 배치하기 위해 도입한 패턴인 슬롯 API를 많이 사용합니다. 이 접근 방식을 사용하면 하위 요소의 모든 구성 매개변수를 노출하지 않고 자체적으로 하위 요소를 구성할 수 있으므로 구성요소의 유연성이 향상됩니다.
슬롯은 개발자가 원하는 대로 채울 수 있도록 UI에 빈 공간을 남겨둡니다. 예를 들어 다음은 개발자가 TopAppBar
에서 맞춤설정할 수 있는 슬롯입니다.
컴포저블은 일반적으로 content
컴포저블 람다(content: @Composable
() -> Unit
)를 사용합니다. 슬롯 API는 특정 용도를 위해 여러 content
매개변수를 노출합니다.
예를 들어 TopAppBar
를 사용하면 title
, navigationIcon
및 actions
의 콘텐츠를 제공할 수 있습니다.
예를 들어 Scaffold
를 사용하면 기본 머티리얼 디자인 레이아웃 구조로 UI를 구현할 수 있습니다. Scaffold
는 TopAppBar
, BottomAppBar
, FloatingActionButton
, Drawer
등 가장 일반적인 상위 머티리얼 구성요소용 슬롯을 제공합니다. Scaffold
를 사용하면 이러한 구성요소가 적절하게 배치되어 함께 올바르게 작동하는지 쉽게 확인할 수 있습니다.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- Compose 수정자
- Jetpack Compose용 Kotlin
- Material 구성요소 및 레이아웃