#1 ๊ฐ์
๋ง์ถค ๋ ์ด์์ | Jetpack Compose | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ๋ง์ถค ๋ ์ด์์ ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. Compose์์ UI ์์๋ ํธ์ถ๋ ๋ UI ์์
developer.android.com
์ ๊ณต์ ๋ฌธ์๋ฅผ ๋๋ง์ ์ธ์ด๋ก ์ ๋ฆฌํ๋ค.
#2 ์ ํํ '๋ฌด์'์ ์ปค์คํ ํ๋๊ฐ?

๊ฒ์๊ธ [Android] App layout - ๊ธฐ์ด์ ์๋ ๋์๋๋ค. ์ด ๋์๋๋ Layout ๋ด๋ถ์ ๋์ ๊ธฐ์ ๋ฅผ ํํํ๊ณ ์๋ค. Layout์ ์ปค์คํ
ํ๋ค๋ ๊ฑด ์ ๋์๋์์ ์ฃผํฉ์ ๋ค๋ชจ ๋ฐ ํ๋์ ๋ค๋ชจ ์์ ๋ด์ฉ์ ์ค๋ฒ๋ผ์ด๋ํ๋ ๊ฒ์ด๋ค.
#3 Modifier.layout()
#3-1 ๊ฐ๋จํ UI
์ฝ๋
Scaffold(
modifier = Modifier.fillMaxSize()
) { innerPadding ->
// ์ฒซ๋ฒ์งธ Box()
Box(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
// ๋๋ฒ์งธ Box()
Box(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Color.Gray), // ๋ถํฌ๋ช
ํ์
contentAlignment = Alignment.Center
) {
Text("12345")
}
// ์ธ๋ฒ์งธ Box()
Box(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Color(0x8000FF00)), // ๋ฐํฌ๋ช
์ด๋ก์
contentAlignment = Alignment.Center
) {
Text("321")
}
}
}
์ฒซ๋ฒ์งธ Box()๋ ๋๋ฒ์งธ Box() ๋ฐ ์ธ๋ฒ์งธ Box()์ ๋ถ๋ชจ๋ค.
์คํฌ๋ฆฐ์ท

์คํฌ๋ฆฐ์ท์ ์์ ๊ฐ๋ค.
#3-2 placeable์ ์๋ฏธ
์ฝ๋
Scaffold(
...
) { ...
// ์ฒซ๋ฒ์งธ Box()
Box(
...
) {
// ๋๋ฒ์งธ Box()
...
// ์ธ๋ฒ์งธ Box()
Box(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Color(0x8000FF00)) // ๋ฐํฌ๋ช
์ด๋ก์
.customLayoutModifier(),
contentAlignment = Alignment.Center
) {
Text("321")
}
}
}
fun Modifier.customLayoutModifier() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(placeable.width, placeable.height) {
placeable.place(
x = 0,
y = 0
)
}
}
Modifier.layout()์ ์ปค์คํ
๋ ์ด์์์ ๋ง๋๋ ํจ์๋ค. ์ด ํจ์๋ฅผ ์ธ๋ฒ์งธ Box()์ ์ ์ฉํ๋ค. ํ์ง๋ง, ๊ทธ ๊ตฌํ ๋ด์ฉ์ ๋ณ ๊ฒ ์๋ค. ์ฌ์ ํ #3-1๊ณผ ๊ฐ์ ํ๋ฉด์ด ๋์ค๊ฒ๋ ๋ง๋ค์๋ค. layout()๋ ํ๋์ ๋๋ค ํจ์๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ณด์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋๋ค ํจ์๋ 2๊ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ง๋ค. ๋ฐ๋ก measurable๊ณผ constraints๋ค.
measurable์ content ํ๋กํผํฐ์ ์์ญ์ ์๋ฏธํ๋ค (๋ง์ ์ปดํฌ์ ๋ธ ํจ์๋ content๋ผ๋ ์ด๋ฆ์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋ค). ๋ณธ ์ฝ๋์์๋ Box()์ content ํ๋กํผํฐ๊ฐ ๋๊ฒ ๋ค.
constraints๋ layout()์ด ๋ถ์ ์ปดํฌ์ ๋ธ์ ๋ถ๋ชจ ์ปดํฌ์ ๋ธ ์ฆ, ์ฒซ๋ฒ์งธ Box()์ ์ ์ฝ์กฐ๊ฑด์ ์๋ฏธํ๋ค.
measurable.measure(constraints)์ ์๋ฏธ๊ฐ ๋ญ๊น? ๋ฐ๋ก #2 ๋์๋์ ์๋ ์ฃผํฉ์ ๋ค๋ชจ๋ค. ๊ทธ๋ ๋ค๋ฉด ์ ์ฝ๋ ์ measurable.measure(constraints)๋ '์ธ๋ฒ์งธ Box()์ ๋ํ ์ธก์ ์์ฒญ'์ด๋ผ๋ ์๋ฏธ๊ฐ ๋๋ค. ๋์๋์์๋ ์ ์ ์๋ฏ์ด, ์ธก์ ์์ฒญ์ ๋ฐ์ ๋
ธ๋์ ์์ ๋
ธ๋๊ฐ ์กด์ฌํ๋ฉด ์ฌ๊ท์ ์ผ๋ก ์์ ๋
ธ๋๋ค์ ์ฃผํฉ์ ๋ค๋ชจ(์ธก์ ์์ฒญ) ๋ฐ ํ๋์ ๋ค๋ชจ(ํฌ๊ธฐ์ ์์น ๊ฒฐ์ )์ด Trigger๋๋ค. ๋ฐ๋ผ์ ์ต์ข
์ ์ผ๋ก placeable์ ๋ด๊ธฐ๋ ๊ฒ์ 'ํฌ๊ธฐ์ ์์น๊ฐ ๊ฒฐ์ ๋ ๋ชจ๋ ์์๋ค์ ๋ชจ์'์ด๋ค.
๋๋ ์ ์ฝ๋๋ฅผ layout()์ด ๋ถ์ง ์์ #3-1์ ์ฝ๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋๋ก ๋ง๋ค์๋ค๊ณ ํ๋ค. ์ฆ, ์ ์ฝ๋๋ ์ปค์คํ
์ด ๊ฐ๋ฏธ๋์ง ์์, Compose์ ๊ธฐ๋ณธ ๋์์ด๋ผ๋ ๋ง์ด๋ค. ์ฌ๊ธฐ์์ ๋ด๊ฐ measure()์ ์ธ์์ ์ฒซ๋ฒ์งธ Box()์ ์ ์ฝ์กฐ๊ฑด์ ๋ฃ์ ์ด์ ๋ฅผ ์ ์ ์๋ค. ๋ฐ๋ก '(#2์ ๋์๋์์ ์ ์ ์๋) ์ปดํฌ์ ๋ธ์ ๊ณ์ธต ๊ด๊ณ'์์ ์์์ ๋ํ ์ธก์ ์์ฒญ์ ๋ถ๋ชจ์ ์ํด Trigger๋๋ค๋ ์ด์ ์์๋ค. ์ธ๋ฒ์งธ Box()์ ๋ฐฐ์น๋ ์ฒซ๋ฒ์งธ Box()์ ์ํด ์ํ๋๋ค. ๊ทธ๋ ๊ธฐ์ (์ปค์คํ
์์ด ์์ ์ผ๋ก ํ๋ก๊ทธ๋๋ฐํ๋ ค๋ฉด) ์ธ๋ฒ์งธ Box()๋ ์ฒซ๋ฒ์งธ Box์ ์ ์ฝ ์กฐ๊ฑด์ ์ง์ผ์ผ๋ง ํ๋ ๊ฒ์ด๋ค.
์คํฌ๋ฆฐ์ท

#3-1๊ณผ ๋๊ฐ์ ํ๋ฉด.
#3-3 MeasureScope.layout()
์ฝ๋ 1
fun Modifier.customLayoutModifier() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(placeable.width, placeable.height) {
placeable.place(
x = 0,
y = 0
)
}
}
์ด์ measurable.measure(constraints) ์๋์ ์๋ MeasureScope.layout()์ ๋ํด ์ค๋ช
ํ๋ค. Modifier.layout()๊ณผ ์ด๋ฆ์ ๊ฐ์ง๋ง ๋ค๋ฅธ ํจ์๋ค.
measurable.measure(constraints)๊ฐ #2 ๋์๋์ ์ฃผํฉ์ ๋ค๋ชจ์ ํด๋นํ๋ค๋ฉด, MeasureScope.layout()๋ ํ๋์ ๋ค๋ชจ์ ํด๋นํ๋ค. ์๊ธฐ ์์ ์ ํฌ๊ธฐ์ ์์น๋ฅผ ๊ฒฐ์ ํ๊ณ , ์์๋ค์ ๋ฐฐ์นํ๋ค. #3-2์์ placeable์ ๋ด๊ธฐ๋ ๊ฒ์ 'ํฌ๊ธฐ์ ์์น๊ฐ ๊ฒฐ์ ๋ ๋ชจ๋ ์์๋ค์ ๋ชจ์'์ด๋ผ๊ณ ํ๋ค. ์ด์ '๋จ์ ๋จ๊ณ(ํ๋์ ๋ค๋ชจ)'๋ ์ธ๋ฒ์งธ Box()์ ํฌ๊ธฐ ๋ฐ ์์น ๊ฒฐ์ ๊ณผ ๋ชจ์์ ์ค์ ๋ฐฐ์น๋ค.
MeasureScope.layout()์ ์ธ์ width ๋ฐ height์ ์ด๋ค ๊ฐ์ ์ ๋ฌํ๋๋ ๋ฐ๋ผ ์๊ธฐ ์์ ์ ํฌ๊ธฐ๊ฐ ๊ฒฐ์ ๋๋ค. ์ ์ฝ๋์์๋ placeable.width ๋ฐ placeable.height๋ฅผ ๊ทธ๋๋ก ๋ฃ์ด์ฃผ๊ณ ์๋ค. ๊ทธ๋ ๋ค๋ฉด, ํด๋น ๊ฐ๋ค์ ์์์ธ Text("321")์ ๋๋น ๋ฐ ๋์ด์ผ๊น? ์๋๋ค. ์ธ๋ฒ์งธ Box()์ Modifier์ ํ๋ ์ฝ๋ฉํด๋์๋ ๋๋น(200.dp) ๋ฐ ๋์ด(200.dp) ๊ฐ์ด๋ค. ์ด ํ๋ ์ฝ๋ฉ์ผ๋ก ์ธํด constraints์ ์ ์ฝ ์กฐ๊ฑด์ด 200.dp๋ก ๊ณ ์ ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ด์ํ์ง ์์๊ฐ? ๋๋ #3-2์์ ๋ถ๋ช
ํ constraints๋ ์ธ๋ฒ์งธ Box()๊ฐ ์๋ ์ฒซ๋ฒ์งธ Box()์ ์ ์ฝ ์กฐ๊ฑด์ด๋ผ ์ค๋ช
ํ๋ค. ๋๋น(200.dp) ๋ฐ ๋์ด(200.dp) ๊ฐ์ ์ธ๋ฒ์งธ Box()์ ๊ฐ์ธ๋ฐ ์ด๊ฒ ์ constraints์ ๊ฐ์ ์์ ํด๋ฒ๋ฆฌ๋๊ฐ?
๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด Modifier.width()๋ Modifier.height()์ ๊ฐ์ ํฌ๊ธฐ ๊ด๋ จ Modifier๊ฐ ๋ถ์ผ๋ฉด, Jetpack Compose ์ปดํ์ผ๋ฌ๊ฐ ๋ถ๋ชจ์ constraints๋ฅผ ๋ฌด์ํ๊ณ ์๋กญ๊ฒ (Modifier.width()๋ Modifier.height()์ ์ํด) ์์ ๋ constraints๋ฅผ ๋ง๋ค์ด ์ ๋ฌํ๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ ์ฝ๋๋ก ์ด ์ฌ์ค์ ์ฆ๋ช
ํด๋ณด์ด๊ฒ ๋ค.
์ฝ๋ 2
Scaffold(
...
) { ...
// ์ฒซ๋ฒ์งธ Box()
Box(
...
) {
// ๋๋ฒ์งธ Box()
...
// ์ธ๋ฒ์งธ Box()
Box(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Color(0x8000FF00)) // ๋ฐํฌ๋ช
์ด๋ก์
.customLayoutModifier(),
contentAlignment = Alignment.Center
) {
Text("321")
}
}
}
fun Modifier.customLayoutModifier() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
Log.d("interfacer_han", "constraints: $constraints")
layout(placeable.width, placeable.height) {
placeable.place(
x = 0,
y = 0
)
}
}
๊ธฐ์กด ์ฝ๋์ Log.d( ... )๋ฅผ ์ถ๊ฐํ๋ค. ๋ก๊ทธ ๋ฉ์์ง๋ก "constraints: Constraints(minWidth = 600, maxWidth = 600, minHeight = 600, maxHeight = 600)"๊ฐ ์ถ๋ ฅ๋๋ค. 200์ด ์๋๋ผ 600์ธ ์ด์ ๋ ๋จ์์ ์ฐจ์ด ๋๋ฌธ์ด๋ค. ๋ณธ ํ๋ก์ ํธ์์ 200.dp๋ 600.px์ด๋ค. ์ด์จ๋ , ์ constraints๋ "๊ทธ๋ฅ ๋ฌด์กฐ๊ฑด 600.px๋ก ์ค์ ํด!"๋ผ๊ณ ๋งํ๋ ๋ฏ ํ๋ค. ๊ทธ์ผ๋ง๋ก ํ๋ ์ฝ๋ฉ์ด๋ค.
์ฝ๋ 3
Scaffold(
...
) { ...
// ์ฒซ๋ฒ์งธ Box()
Box(
...
) {
// ๋๋ฒ์งธ Box()
...
// ์ธ๋ฒ์งธ Box()
Box(
modifier = Modifier
.background(Color(0x8000FF00)) // ๋ฐํฌ๋ช
์ด๋ก์
.customLayoutModifier(),
contentAlignment = Alignment.Center
) {
Text("321")
}
}
}
fun Modifier.customLayoutModifier() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
Log.d("interfacer_han", "constraints: $constraints")
layout(placeable.width, placeable.height) {
placeable.place(
x = 0,
y = 0
)
}
}
๋ฐฉ๊ธ ์ฝ๋์์ ์ธ๋ฒ์งธ Box()์ Modifier.width() ๋ฐ Modifier.height()๋ฅผ ์ ๊ฑฐํ๋ค. ๋ก๊ทธ ๋ฉ์์ง๋ก "constraints: Constraints(minWidth = 0, maxWidth = 1344, minHeight = 0, maxHeight = 2769"๊ฐ ์ถ๋ ฅ๋๋ค. ์ด๊ฒ ์ง์ง, ๊ฐ๋ก์ฑ์ง์ง ์์ ์ฒซ๋ฒ์งธ Box()์ constraints๋ค.
#3-4 ์ปค์คํ - ์์์ ๋ฐฐ์น
์ฝ๋ 1
Scaffold(
...
) { ...
// ์ฒซ๋ฒ์งธ Box()
Box(
...
) {
// ๋๋ฒ์งธ Box()
...
// ์ธ๋ฒ์งธ Box()
Box(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Color(0x8000FF00)) // ๋ฐํฌ๋ช
์ด๋ก์
.customLayoutModifier(),
contentAlignment = Alignment.Center
) {
Text("321")
}
}
}
fun Modifier.customLayoutModifier() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(placeable.width, placeable.height) {
placeable.place(
x = 100,
y = 100
)
}
}
x = 100, y = 100 ๋ถ๋ถ์ ์ ์ธํ๋ฉด #3-2์ ๋์ผํ ์ฝ๋๋ค. placeable.place()๋ MeasureScope.layout()์ placementBlock ํ๋กํผํฐ์ ํด๋นํ๋ ๋ถ๋ถ์ผ๋ก, ํํ๋ Placeable.PlacementScope.() -> Unit ์ด๋ค. ์ฌ๊ธฐ์๋ #2 ๋์๋์ ํ๋์ ๋ค๋ชจ์ ๋ด์ฉ ์ค, ์์๋ค์ ๋ชจ์์ ๋ฐฐ์นํ๋ ๋ถ๋ถ์ ํด๋นํ๋ค. Jetpack Compose์์๋ ๋งจ โ์ชฝ ์ขํ๊ฐ (0, 0)์ด๋ค. ๋ฐ๋ผ์ (100, 100)์ โ์ชฝ์ผ๋ก 100ํฝ์
, โ์ชฝ์ผ๋ก 100ํฝ์
๋งํผ ๋จ์ด์ ธ ๋ฐฐ์นํ๋ผ๋ ๋ง์ด ๋๋ค. ์คํฌ๋ฆฐ์ท์ ํ์ธํด๋ณด์.
์คํฌ๋ฆฐ์ท 1

์์งํ, ๋ญ๊ฐ ์ด๋ป๊ฒ ๋๊ฑด์ง ๊ฐ์ด ์์กํ๋ค. ๊ทธ๋์ ์ฝ๋๋ฅผ ์ฝ๊ฐ ์์ ํ๋ค.
์ฝ๋ 2
Scaffold(
...
) { innerPadding ->
// ์ฒซ๋ฒ์งธ Box()
Box(
...
) {
// ๋๋ฒ์งธ Box()
...
// ์ธ๋ฒ์งธ Box()
Box(
modifier = Modifier
.width(200.dp)
.height(200.dp)
.background(Color(0x4000FF00)) // ๋ฐํฌ๋ช
์ด๋ก์
.customLayoutModifier()
.background(Color(0x60FF00FF)), // ๋ฐํฌ๋ช
๋ณด๋ผ์
contentAlignment = Alignment.Center
) {
Text("321")
}
}
}
customLayoutModifier() ๋ค์ background(Color(0x60FF00FF))๋ฅผ ์ถ๊ฐํด๋ดค๋ค. ๋ค์ ์คํฌ๋ฆฐ์ท์ ๋ณด์.
์คํฌ๋ฆฐ์ท 2

์ด์ ์ผ ๊ฐ์ด ์ข ์กํ๋ค. ์ด๋ก์ ๋ค๋ชจ๋ 3๋ฒ์งธ Box()์ ์์ญ์ด๋ค. ์ด๋ก์ ๋ค๋ชจ์ ์์ญ์ ๊ทธ๋๋ก โ์ชฝ์ผ๋ก 100ํฝ์
๋งํผ โ์ชฝ์ผ๋ก 100ํฝ์
๋งํผ ์์ง์ธ๊ฒ ๋ฐ๋ก, 3๋ฒ์งธ Box()์ '์์๋ค์ ๋ชจ์์ ์์ญ(๋ณด๋ผ์ ๋ค๋ชจ)'์ด ๋ ๊ฒ์ด๋ค.
ํน์ ์ธ๋ฒ์งธ Box(), ์ฆ ์ด๋ก์ ์์ญ์ ์ ์ ์์ง์ด๋ ๊ฑด์ง ๊ถ๊ธํ ์ฌ๋๋ ์๊ฒ ๋ค. ๊ทธ๋ฐ ์ฌ๋๋ค์ #2 ๋์๋์ ํ๋์ ๋ค๋ชจ๋ฅผ ๋ค์ ๋ณด๋ผ. ์์๋ค์ ๋ชจ์์ ๋ฐฐ์นํ๋๊ฑฐ์ง, ์๊ธฐ ์์ ์ ๋ฐฐ์นํ์ง๋ ์๋๋ค. ์ธ๋ฒ์งธ Box()์ ์์ญ ๋ฐฐ์น๋, ์ฒซ๋ฒ์งธ Box()๊ฐ ์ํํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ฒซ๋ฒ์งธ Box()์๋ contentAlignment = Alignment.Center๊ฐ ์ ์ฉ๋์ด์๋ค (#3-1 ์ฐธ์กฐ). ๋ฐ๋ผ์ ์ฒซ๋ฒ์งธ Box()์ ์ ๋ ฌ ๊ท์น์ ๋ฐ๊พธ์ง ์๋ ํ, ์ธ๋ฒ์งธ Box()๋ ๋ฌด์จ ์ง์ ํด๋ ๋ฐ๋์ ์ ์ค์์ ์์นํ๋ค.
#3-5 ์ปค์คํ - ์์ ์ ํฌ๊ธฐ
์ฝ๋
fun Modifier.customLayoutModifier() = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(placeable.width + 300, placeable.height + 300) {
placeable.place(
x = 100,
y = 100
)
}
}
#3-4์ ์ฝ๋ 2์ ๋น๊ตํด placeable.width + 300, placeable.height + 300 ๋ถ๋ถ์ ์ ์ธํ๋ฉด ๊ฐ์ ์ฝ๋๋ค. ์ด๋ฌ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
์คํฌ๋ฆฐ์ท

์คํฌ๋ฆฐ์ท์ ๋นจ๊ฐ์ ์ ๊ณผ ์ฃผํฉ์ ์ ์ ๋ด๊ฐ ์คํฌ๋ฆฐ์ท์ ๊ทธ๋ฆผํ์ผ๋ก ์ด์ด์ ๋ฐ๋ก ์ฐ์ ๊ฒ์ด๋ค. ์ธ๋ฒ์งธ Box()์ ๋๋น์ ๋์ด๊ฐ ๊ฐ๊ฐ 300ํฝ์
์ฉ ์ปค์ก๋ค. ๊ทธ๋์ ์ธ๋ฒ์งธ Box()์ (0, 0) ๊ธฐ์ค์ ์ด ์ฃผํฉ์ ์ ์์ ๋นจ๊ฐ์ ์ ์ผ๋ก ์ด๋ํ๋ค. ๋ณด๋ผ์ ์์ญ์ ์ฌ์ ํ (0, 0)๋ก๋ถํฐ โ์ชฝ์ผ๋ก 100ํฝ์
๋งํผ โ์ชฝ์ผ๋ก 100ํฝ์
๋งํผ ์์ง์ธ ๊ณณ์ ์์นํ๋ค.
#4 Layout()
#4-1 ์ผ๊ด์ ์ปค์คํ
Layout()์ ์์ ์ดํด๋ณธ Modifier.layout()์ ๋์์ ์ผ๊ด์ ์ผ๋ก ์ํํ๋ค. ์ด๋ค ์ปดํฌ์ ๋ธ์ด ์ฌ๋ฌ ์์์ ๊ฐ์ง๊ณ ์๋๋ฐ, ๊ทธ ์์๋ค์ ๊ฐ๊ฐ ๋ฐ๋ก ์ปค์คํ
ํด์ค ๋ Layout()์ ์ฌ์ฉํ๋ค.
#4-2 ๊ฐ๋จํ UI
์ฝ๋
Scaffold(
modifier = Modifier.fillMaxSize()
) { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
) {
Text(text = "11111", fontSize = 32.sp)
Text(text = "22222", fontSize = 32.sp)
Text(text = "33333", fontSize = 32.sp)
Text(text = "44444", fontSize = 32.sp)
Text(text = "55555", fontSize = 32.sp)
}
}
๊ฐ๋จํ Column์ด๋ค.
์คํฌ๋ฆฐ์ท

์คํฌ๋ฆฐ์ท์ ์์ ๊ฐ๋ค.
#4-3 ์ปค์คํ
์ฝ๋
Scaffold(
modifier = Modifier.fillMaxSize()
) { innerPadding ->
ReplicatedColumn(
modifier = Modifier.padding(innerPadding)
) {
Text(text = "11111", fontSize = 32.sp)
Text(text = "22222", fontSize = 32.sp)
Text(text = "33333", fontSize = 32.sp)
Text(text = "44444", fontSize = 32.sp)
Text(text = "55555", fontSize = 32.sp)
}
}
@Composable
fun ReplicatedColumn(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = content
) { measurables, constraints ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
/* ReplicatedColumn์ ํฌ๊ธฐ๋ฅผ ๊ฐ๋ฅํ ํ ํฌ๊ฒ (= ๋ถ๋ชจ์ ์ต๋ ๋๋น ๋ฐ ์ต๋ ๋์ด๋ฅผ ์ง๋๋๋ก) ์ค์
* ๋ณธ ์ฝ๋์์๋, ReplicatedColumn์ ๋ถ๋ชจ์ธ Scaffold๊ฐ ๊ฐ์ง ์ ์๋ ์ต๋ ํฌ๊ธฐ๋ก ์ค์
*/
layout(constraints.maxWidth, constraints.maxHeight) {
var yPosition = 0
placeables.forEach { placeable ->
placeable.place(x = 0, y = yPosition)
yPosition += placeable.height
}
}
}
}
#4-2๋ฅผ Column() ๋์ Layout()์ ์ด์ฉํด ๊ตฌํํด๋ณด์๋ค. ์์ธํ ์ค๋ช
์ #3์์ ํ์ผ๋ฏ๋ก ์๋ตํ๋ค. MeasureScope.layout()์์ ReplicatedColumn์ ํฌ๊ธฐ๋ฅผ ์ต๋๋ก ์ค์ ํ๊ธฐ์, Column์ ๋ถ์๋ fillMaxSize()๋ ์ ๊ฑฐํ๋ค. ์ ๊ฑฐํ์ง ์๋๋ผ๋ ๊ฒฐ๊ณผ๋ ์ด์ฐจํผ ๊ฐ๊ฒ ์ง๋ง.
Layout()์ ๋๋ค ํจ์๋ Modifier.layout()์ ๋๋ค ํจ์์๋ ๋ฌ๋ฆฌ, measurable ๋์ measurable's'์ ๋งค๊ฐ๋ณ์๋ก ๊ฐ์ง๋ค. ์ผ๊ด์ ์ผ๋ก ๋ณต์ ๊ฐ์ ์์ ์ปดํฌ์ ๋ธ์ ์ปค์คํ
ํด์ผํ๋ ๊ทธ๋ ๋ค. ๊ทธ๋ ๊ธฐ์ placeable ๋์ placeable's'์ ์ฐ๊ณ , placeable.place()๋ forEach๋ฌธ์ ๋ค์ด๊ฐ ์๋ ๋ชจ์ต์ ํ์ธํ ์ ์๋ค.
์คํฌ๋ฆฐ์ท

#4-2์ ์คํฌ๋ฆฐ์ท์ ๊ทธ๋๋ก ๊ฐ์ ธ์จ ๊ฒ ์๋๊ฐ ์ถ๊ฒ ์ง๋ง, ์๋๋ค. ์ด๊ฑธ๋ก Layout()์ ๋ํ ์ค๋ช
์ ๋ง์น๋ค.
#5 ์์ฝ
์ปค์คํ ๋ ์ด์์์ Compose UI ๊ธฐ์ ๋์๋ ์์ ๊ฐ ๋จ๊ณ๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ๋ค.
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] UI architecture - Phase์ State (1) | 2025.02.27 |
---|---|
[Android] UI architecture - Phases (0) | 2025.02.27 |
[Android] App layout - ๊ธฐ์ด (0) | 2025.02.27 |
[Android] Pointer input - Nested Scroll (0) | 2025.02.18 |
[Android] Pointer input - Scroll (0) | 2025.02.17 |