#1 ๊ฐ์
Compose ๋ ์ด์์ ๊ธฐ๋ณธ์ฌํญ | Jetpack Compose | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. Compose ๋ ์ด์์ ๊ธฐ๋ณธ์ฌํญ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. Jetpack Compose๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ์
developer.android.com
์ ๊ณต์ ๋ฌธ์๋ฅผ ๋์ ์ธ์ด๋ก ์ ๋ฆฌํ๋ค.
#2 ๊ธฐ๋ณธ ์ปดํฌ์ ๋ธ
[Android] Jetpack Compose - Layout, Arrangement, Alignment
#1 Layout#1-1 ๊ฐ์ Compose ๋ ์ด์์ ๊ธฐ๋ณธ์ฌํญ | Jetpack Compose | Android Developers์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. Compose ๋ ์ด์์ ๊ธฐ๋ณธ์ฌํญ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ
kenel.tistory.com
Column(), Row(), Box()๋ ๋ ์ด์์์ ์ํด Jetpack Compose์์ ์ ๊ณต๋๋ ๊ธฐ๋ณธ ์ปดํฌ์ ๋ธ๋ค์ด๋ค. ์ ๊ฒ์๊ธ์ ์ ๋ฆฌํ๋ค.
#3 Layout ์ค๊ณ์ ์์
#3-1 ์ฝ๋
@Composable
fun SearchResult() {
Row {
Image(
// ...
)
Column {
Text(
// ...
)
Text(
// ...
)
}
}
}
์ด ์ฝ๋์ UI Tree๋ ์๋์ ๊ฐ๋ค.
#3-2 UI Tree
SearchResult
Row
Image
Column
Text
Text
์ด UI Tree์ ๊ธฐ๋ฐํด Layout ๋ด๋ถ์ ๋์ ์์๋ฅผ ๋์๋๋ก ๋ํ๋ด๋ฉด ์๋์ ๊ฐ๋ค.
#3-3 Layout ๋ด๋ถ์ ๋์ ์์

ํ์ ๋ค๋ชจ ์ ์ซ์๋ ๋์ ์์๋ค. ์์์ ๊ฐ์ง๋ ๋ถ๋ชจ ๋ ธ๋๋, ์์๋ค์ ํฌ๊ธฐใ์์น๋ฅผ ๋ณด๊ณ ๋ฐ์ ์์ ์ ํฌ๊ธฐใ์์น๋ฅผ ๊ฒฐ์ ํ๋ค. ๋ถ๋ชจ๊ฐ ์์ ์ ํฌ๊ธฐใ์์น๋ฅผ ๊ฒฐ์ ํ๋ฉด, ๋ด๋ถ์ ์์๋ค์ ๋ฐฐ์นํ ๋ค์ ์์ ์ ๋ถ๋ชจ์๊ฒ (์ฌ๊ท์ ์ผ๋ก) ์๊ธฐ ์์ ์ ํฌ๊ธฐใ์์น๋ฅผ ๋ณด๊ณ ํ๋ค. ์ฆ, (์์คํ ๋ ธ๋๋ฅผ ์ ์ธํ) ๋ชจ๋ ๋ ธ๋๋ [์ธก์ ์์ฒญ] โ [๋ฐฐ์น ์ค๋น(ํฌ๊ธฐใ์์น ๊ฒฐ์ )] โ [์ค์ ๋ฐฐ์น]์ ๋จ๊ณ๋ฅผ ๊ฑฐ์น๋ค.
#3-4 ์ผ๋ฐํ์ ์์ธ
Compose์ Layout ๋จ๊ณ๋ ์์ ๊ฐ์ด ๋ถ๋ชจ โ ์์ ๋ฐฉํฅ์ผ๋ก ๋จ ํ๋ฒ๋ง ์ธก์ ์์ฒญ์ ํ๋๋ฐ, ์ด๋ (2๋ฒ ์ด์ ์ธก์ ์ ํ์ง ์๋๋ค๋ ์ ์์) ์๋์ ์ผ๋ก ๋์ ์ฑ๋ฅ์ ๋น๊ฒฐ์ด ๋๋ค. ๊ทธ๋ฌ๋, ํน์ ์ํฉ์์ ์ฌ๋ฌ ๋ฒ์ ์ธก์ ์์ฒญ์ด ํ์ํ ์๋ ์๋๋ฐ ์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ์ํ Intrinsic measurements๋ผ๋ ๋๊ตฌ๊ฐ ์ ๊ณต๋๋ค. Intrinsic measurements๋ ์์ ์ปดํฌ์ ๋ธ์ ์ค์ ๋ก ์ธก์ ํ๊ธฐ ์ ์, ํด๋น ์์์ ์ต์ใ์ต๋ ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ํ์ธ(Query)ํ ์ ์๋ ๊ธฐ๋ฅ์ด๋ค. ์ด๋ '์ค์ ์ธก์ '์ ์๋๊ณ 'Query'์ ๊ฐ๊น์ด ๋์์ด๋ค. ๊ทธ๋ ๊ธฐ์ ์ฌ์ ํ ๋จ ํ๋ฒ์ ์ธก์ ์์ฒญ์ด๋ผ๋ ๊ท์น์ ์ ์ง๋๋ค.
#4 ๋ถ๋ชจ์ ์ ์ฝ ์กฐ๊ฑด
Layout์ ์ค๊ณํ ๋๋ ๋ค์ํ ๋๋ฐ์ด์ค์ ๋ฌผ๋ฆฌ์ ํฌ๊ธฐ(Form Factor)๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ค. Compose์์๋ ์ด๋ฅผ ์ํด BoxWithConstraints()๋ผ๋ ๋๊ตฌ๋ฅผ ์ ๊ณตํ๋ค.
@Composable
@UiComposable
fun BoxWithConstraints(
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
propagateMinConstraints: Boolean = false,
content: @Composable @UiComposable BoxWithConstraintsScope.() -> Unit
): Unit
BoxWithConstraints()๋ BoxWithConstraintsScope๋ฅผ ๋ณด์ ํ๋๋ฐ, ์ด Scope์์๋ ๋ถ๋ชจ ์ปจํ ์ด๋์ ์ต์ ๋์ด, ์ต๋ ๋์ด, ์ต์ ๋๋น, ์ต๋ ๋๋น๋ฅผ ์ฐธ์กฐํ ์ ์๋ค. ์์ ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
@Composable
fun WithConstraintsComposable() {
BoxWithConstraints {
Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
}
}
/* minHeight ๋ฐ maxWidth๊ฐ ์ ๊ฐ์๊ธฐ ํ์ด๋์จ๊ฑธ๊น? ๋ฐ๋ก, Kotlin์ '์์์ this' ๋๋ฌธ.
@Composable
fun WithConstraintsComposable() {
BoxWithConstraints {
// BoxWithConstraintsScope๋ก๋ถํฐ ์ ๊ณต๋๋ ํ๋กํผํฐ๋ค
val minH = this.minHeight // this๋ BoxWithConstraintsScope
val maxW = this.maxWidth
Text("My minHeight is $minH while my maxWidth is $maxW")
}
}
*/
#5 ์ฌ๋กฏ ๊ธฐ๋ฐ Layout
#5-1 ๊ฐ์

์ฌ๋กฏ ๊ธฐ๋ฐ ๋ ์ด์์(Slot-based layout)์ ์ปดํฌ์ ๋ธ์ ์ฌ์ฉ์ํ(customization)์ ์ฌ์ง๊ฐ ์กด์ฌํ๋ ๋ ์ด์์์ ์๋ฏธํ๋ค. ์ฌ์ฉ์ํ๊ฐ ๊ฐ๋ฅํ ๋ถ๋ถ๋ถ๋ถ๋ค์ '์ฌ๋กฏ(Slot)'์ด๋ผ ๋ถ๋ฅด๋๋ฐ Drawer, FloatingActionButton, TopAppBar์ ๊ฐ์ ์์๋ค์ด ๊ทธ ์๋ค. ๊ฐ๋ฐ์๋ ์ด ์ฌ๋กฏ๋ค์ ์ํ๋ ๋ฐฉ์์ผ๋ก ์ฑ์ธ ์ ์๋ค.
#5-2 ์ฌ๋กฏ ์ปค์คํ ์ ์์
@Composable
fun HomeScreen(/*...*/) {
ModalNavigationDrawer(drawerContent = { /* ... */ }) {
Scaffold(
topBar = { /*...*/ }
) { contentPadding ->
// ...
}
}
}
Scaffold()๊ฐ ์ฐ์ธ ์ฝ๋๋ค. ์ปดํฌ์ ๋ธ์ ์์น์ํฌ ์ ์๋ ๋๋ค ํจ์ @Composable () -> Unit๋ ๋๋ถ๋ถ "content"๋ผ๋ ์ด๋ฆ์ ํ๋กํผํฐ๋ก ์กด์ฌํ๋ค. ์ด ํ๋กํผํฐ๊ฐ Slot์ ์๋ฆฌ๋ค.
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] UI architecture - Phase์ State (1) | 2025.02.27 |
---|---|
[Android] UI architecture - Phases (0) | 2025.02.27 |
[Android] Pointer input - Nested Scroll (0) | 2025.02.18 |
[Android] Pointer input - Scroll (0) | 2025.02.17 |
[Android] Pointer input - Gesture (0) | 2025.02.08 |