[Compose] Jetpack Compose Tutorial
Tutorial (https://developer.android.com/jetpack/compose/tutorial)
Lesson 1 : Composable functions
Compose 는 Composable function 으로 구성되어있다.
이 함수들은 Ui 구성에 집중하기 보다 앱이 어떻게 보이는지 설명하고, 데이터 의존성을 제공함으로써 UI 를 정의하도록 한다.
일반 함수를 Compose 함수를 만들려면 @Composable annotation 을 추가하면 된다.
Composable function 은 다른 Composable function 에서만 호출될 수 있다.
- setConent block : setConent 블록은 Composable function 이 호출될 수 있는 액티비티 레이아웃이다. setContentView 의 Compose 버전이라고 생각하면 된다.
Jetpack Compose 는 Kotlin Complier plugin 을 사용하여 Composable function 를 앱의 Ui 요소로 변환한다.
@Composable annotation
- Compose 함수 만들려면 이 annotation 을 추가한다.
@Preview annotation
- 이 annotation 은 Android Studio 에서 앱을 빌드 하지 않고도 Composable 함수를 미리볼 수 있도록 한다.
Preview 함수는 매개변수가 없는 함수여야 한다.
프로젝트를 다시 빌드해도 Preview 함수를 호출하는 곳이 없으므로 앱 자체는 변경되지 않는다. Preview 는 Split 영역에서 미리보기를 제공한다. 이 곳에서 @Preview annotation 이 달린 함수의 UI 를 미리보기로 표시한다.
Lesson 2 : Layouts
UI 요소는 계층적이며, 다른 요소를 포함할 수 있다. Compose 에서는 Composable 함수에서 다른 Composable 함수를 호출하여 UI 계층구조를 만든다.
Column 을 사용하면 UI 요소를 수직으로 정렬할 수 있다.
Row 를 사용하면 UI 요소를 수평으로 정렬할 수 있고, Box 를 사용하면 UI 요소를 쌓을 수 있다.
Composable 을 꾸미거나 구성할 때는 Modifier 를 사용한다.
Modifier 는 Composable 크기, 레이아웃, 모양을 변경하거나 UI 요소를 클릭 가능하여 상위 수준의 상호작용을 가능하게 한다.
@Composable
fun MessageCard(message: Message) {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painterResource(id = R.drawable.profile_picture),
contentDescription = "Contact profile",
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(text = message.author)
Spacer(modifier = Modifier.width(4.dp))
Text(text = message.body)
}
}
}
Lesson 3 : Material Design
Compose 의 많은 UI 요소가 Material Design 을 즉시 사용가능하도록 되어있다.
Theme 과 Surface 로 Composable function 을 래핑하고, Preview 함수에서도 설정하면 Composable 이 앱 테마에 정의된 스타일을 상속하여 앱 전체에서 일관성이 보장된다.
MaterialDesign 은 ui.theme 패키지 하위에 Color, Typography, Shame 의 세가지 핵심 요소로 구성된다.
- Color
MaterialTheme.colors 를 사용해 색상 스타일을 지정할 수 있다.
Image(
painterResource(id = R.drawable.profile_picture),
contentDescription = "Contact profile",
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
)
Text(
text = message.author,
color = MaterialTheme.colors.secondaryVariant
)
- Typography
폰트는 style 에 추가하면 된다.
Text(
text = message.author,
color = MaterialTheme.colors.secondaryVariant,
style = MaterialTheme.typography.subtitle2
)
- Shape
도형으로 최종 디자인을 마무리 할 수 있다.
Surface(shape = MaterialTheme.shapes.medium, elevation = 1.dp) {
Text(
text = message.body,
modifier = Modifier.padding(all = 4.dp),
style = MaterialTheme.typography.body2
)
}
- Dark Mode Theme
Preview 에 name 을 통해 Dark Mode 를 사용할 수 있다.
파일에서 별도의 함수로 여러 Preview 를 만들거나, 또는 하나의 함수에 여러 Preview 를 만들 수 있다.
@Preview(name = "Light Mode")
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
Lesson 4 : List 와 Animation
- LazyColumn, LazyRow
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
messages.map {
item {
MessageCard(message = it)
}
}
}
}
위 코드에서 LazyColumn 에 하위요소로 item 이 있는 것을 알 수 있다.
item 은 List 를 파라미터로 가져오고, item 의 람다는 Message 의 instance 인 message 라는 매개변수를 받는다.
이 람다는 List 항목마다 호출된다. (여기 부분은 이해가 안되네. 코드는 이해가 되는데 내용이 이해가 안 감)
- Animation
var isExpanded by remember { mutableStateOf(false) }
Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
// 생략
}
Local Ui 상태를 저장하여 관리할 수 있다.
상태 변경을 추적하려면 remember 와 mutableStateOf 함수를 사용한다.
Composable function 은 remember API 를 사용해 메모리에 로컬 상태를 저장하고 mutableStateOf 에 전달된 값의 변경사항을 추적할 수 있다. 이 변수를 사용하는 하위 요소는 값이 업데이트 되면 자동으로 다시 그려지는데 이것을 Recomposition 이라고 한다.
변수에 remember 나 mutableStateOf 같은 Compose State API 를 사용하여 상태를 변경하면 UI 가 자동으로 업데이트 된다.
* by 를 올바르게 사용하려면 getValue, setValue 구문을 import 해야한다.
val surfaceColor by animateColorAsState(
targetValue = if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface
)
animateColorAsState 함수를 사용하여 값을 점진적으로 수정되는 애니메이션을 줄 수 있다.
animateContentSize modifier 으로 부드럽게 애니메이션을 줄 수 있다.
궁금한 것
- Preview 의 showBackground 는 무엇인가?
- Compose 함수는 왜 대문자로 시작하는가?
- LazyColumn 의 람다 이야기가 이해가 안된다.