#1 ๊ฐ์
์คํฌ๋กค | Jetpack Compose | Android Developers
์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ์คํฌ๋กค ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์ ์ ๊ธฐ์ค์ผ๋ก ์ฝํ ์ธ ๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฅํ์ธ์. ์ฐธ๊ณ : ํญ๋ชฉ ๋ชฉ๋ก์ ํ์ํ๋ ค๋ฉด ์ด๋ฌํ API ๋์
developer.android.com
์ ๊ณต์ ๋ฌธ์๋ฅผ ๋์ ์ธ์ด๋ก ์ ๋ฆฌํ๋ค.
#2 ์คํฌ๋กค'๋๋' Modifier
#2-1 Modifier.verticalScroll()
fun Modifier.verticalScroll(
state: ScrollState,
enabled: Boolean = true,
flingBehavior: FlingBehavior? = null,
reverseScrolling: Boolean = false
): Modifier
๋น์ ์ด ํ์ฌ ๋ณด๊ณ ์๋ ์ด ํ์ด์ง๋ ๋ชจ๋ํฐ๋ณด๋ค ํด ๊ฒ์ด๋ค. ๊ทธ๋์ ๋น์ ์ ๋ง์ฐ์คํ ๋ก ์ด ํ์ด์ง๋ฅผ ์คํฌ๋กคํ๊ณ ์๋ค. verticalScroll()์ ์ด๋ค ์ฝํ ์ธ ๊ฐ ํด๋น ์ฝํ ์ธ ๊ฐ ๋ด๊ธด ์ปจํ ์ด๋๋ณด๋ค (์ธ๋ก ๋ฐฉํฅ์ผ๋ก) ํด ๋, ๋ณธ ํจ์๋ฅผ ํตํด ์ปจํ ์ด๋๋ฅผ ์์ง ์คํฌ๋กคํ๊ฒ ๋ง๋ค์ด์ค๋ค. ๋ฐ๋๋ก verticalScroll()์ด ๋ถ์ฌํ๋ค๋ฉด, ์ปจํ ์ด๋๋ณด๋ค ์ฝํ ์ธ ๊ฐ ํผ์๋ ์คํฌ๋กคํ ์ ์๋ค.
#2-2 Modifier.horizontalScroll()
fun Modifier.horizontalScroll(
state: ScrollState,
enabled: Boolean = true,
flingBehavior: FlingBehavior? = null,
reverseScrolling: Boolean = false
): Modifier
verticalScroll()์ ์ํ ๋ฒ์ .
#3 ์คํฌ๋กค '๊ฐ๋ฅํ' Modifier
#3-1 Modifier.scrollable()
fun Modifier.scrollable(
state: ScrollableState,
orientation: Orientation,
enabled: Boolean = true,
reverseDirection: Boolean = false,
flingBehavior: FlingBehavior? = null,
interactionSource: MutableInteractionSource? = null
): Modifier
์ด๋ฆ ํ ๋ฒ ๋ชป ์ง์๋ค. verticalScroll()๊ณผ ๋ฌ์์ค๊ฐ ๋๋ฌด๋๋ ๊ฒน์น์ง ์๋๊ฐ? ๋ช ๋ฐฑํ๊ฒ ๋ค๋ฅธ ๋์์ ํ๋ ํจ์์์๋ ๋ง์ด๋ค. "'์' ๋ค๋ฅด๊ณ '์ด' ๋ค๋ฅด๋ค"๋ผ๋ ๋ง์ ๋ค์ด๋ณธ ์ ์ด ์์ ๊ฒ์ด๋ค. ๊ทธ ๋ง๋งํผ ์ด ํจ์๋ฅผ ์ ์ค๋ช ํ๋ ๋ง์ ์ฐพ๊ธฐ ์ด๋ ค์ธ ๊ฒ์ด๋ค. ๊ฒฐ๋ก ๋ถํฐ ๋งํ์๋ฉด scrollable() ํจ์๋,
์ด๋ค ์ปจํ ์ด๋๋ฅผ ์คํฌ๋กค ๊ฐ๋ฅ์ผ ๋ง๋ค์ง๋ง, ๊ทธ๋ ๋ค๊ณ ์คํฌ๋กค์ด ๋๊ฒ ๋ง๋ค์ง ์๋ ํจ์
๋ค. ์ด ์ ์๊ฐ ํผ๋์ค๋ฌ์ธ ์๋ฐ์ ์์ ๊ฒ์ด๋ค. ์ด๊ฑด ์์ ์ฝ๋์ ๊ทธ ์์ ์ฝ๋๊ฐ ๋์ํ๋ GIF ํ์ผ์ ๋ณด๋ ์๋ฐ์ ์๋ค. ๋ฐ๋ก ์๋์์ ์ด์ด์ง๋ค.
#3-2 ์์ ์ฝ๋์ ๊ทธ ๊ฒฐ๊ณผ
์ฝ๋
@Composable
private fun ScrollableSample() {
// ํฉ์ฐ ์คํฌ๋กค๋์ ์ ์ฅํ State
var offset by remember { mutableStateOf(0f) }
Box(
Modifier
.size(150.dp)
.scrollable(
orientation = Orientation.Vertical,
// ๋งค ์คํฌ๋กค๋ง๋ค ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์
state = rememberScrollableState { delta ->
offset += delta // ์์ง ์คํฌ๋กค ๋ณํ๋(delta)๋ฅผ offset์ ๋ํด๋๊ฐ
delta
}
)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
Text(offset.toString())
}
}
Box()์ scrollable()์ ์ ์ฉํ๋ค. ์ด์ ์ด Box()๋ ์์์ ๋งํ๋๋ก, '์คํฌ๋กค์ด ๊ฐ๋ฅํ์ง๋ง ๊ทธ๋ ๋ค๊ณ ์คํฌ๋กค์ด ๋์ง๋ ์์์ผ' ํ๋ค.
๊ฒฐ๊ณผ ๊ทธ๋ฆฌ๊ณ ๋ชฉ์
๋ GIF ์ด๋ฏธ์ง๋ฅผ ๋ณด๊ณ ๋์์ผ ๋น๋ก์, ์คํฌ๋กค ๊ฐ๋ฅํ๋คํ์ง ๋๋ค๊ณ ๋ ์ ํ๋ค๋ ๋ง์ ๋ฌ์์ค๋ฅผ ์๊ฒ ๋๋ค. ๋, scrollable()์ ๋ชฉ์ ๋ ์ง๊ด์ ์ผ๋ก ๋๊ปด์ง๋ค. ๋ฐ๋ก ์คํฌ๋กค ์ธก์ ์ด๋ค. ์ธก์ ์ ์ ์ ์กฐ๊ฑด์, ์คํฌ๋กค์ด ๊ฐ๋ฅ(able)ํด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
#3-3 ScrollableState
scrollable()์ ๋งค๊ฐ๋ณ์ ์ค์ ScrollableState๊ฐ ์๋ค. ์คํฌ๋กค(Scroll) ๊ฐ๋ฅํ(able) ์ํ(State)๋ผ๋. ๋ฐ๋ก ์์์ ์ธ๊ธํ๋ scrollable()์ ๋ชฉ์ ์ ๊ธฐ๋ฐํด ์๊ฐํด ๋ณด๋ฉด ScrollableState๋ ์คํฌ๋กค ์ธก์ ๊ณผ ๊ด๋ จ๋ ๊ฐ์ฒด์์ ๋ถ๋ช ํ๋ค. verticalScroll()์ ScrollState๊ฐ ํ์ฌ ์ด๋ ์ ๋ ์คํฌ๋กค ๋์๋์ง์ ๊ฐ์ ๋ณด์ ํ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ, ScrollableState๋ ๊ทธ๋ฐ ๊ฐ ๋์ ์ด๋ค ์ฝ๋ฐฑ ํจ์ ํ๋๋ง์ ์ ์ฅํ๋ค. ๊ทธ๋์ ์ด ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค๋ ค๋ฉด ์์ฑ์์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ฌํด ์ค์ผ ํ๋ค.
#3-4 ScrollableState์ ์ฝ๋ฐฑ ํจ์
์คํฌ๋กค ์ธก์ ์ ๋ฐฉ์์ ์ ์ํ๋ค. '์ธก์ '์ด๋ผ๋ ๋จ์ด๋ฅผ ๋ฌธ์ฅ์ผ๋ก ๋ฐ๊พธ๋ฉด '์ผ๋ง๋ ์คํฌ๋กค๋์๋๊ฐ?'๋ค. ๊ทธ๋ ๋ค๋ฉด '์ธก์ ์ ๋ฐฉ์'์ "์ธก์ ์ ์ด๋ป๊ฒ ํธํฅ์ํฌ ๊ฒ์ธ๊ฐ?"๊ฐ ๋๋ค. ์ด๋ ๋ง์น ์ค๋ฆฝ์ ์งํค์ง ์๋ ์ธ๋ก ์ฌ๊ฐ ์ค์ ๋ชจ์ต๊ณผ ๋ณด๋ ๋ด์ฉ์ ์์ดํ๊ฒ ํธํฅ์ํค๋ ๊ฒ๊ณผ ๊ฐ๋ค.
ScrollalbeState๊ฐ ๋ณด์ ํ๋ ์ฝ๋ฐฑ ํจ์๋ Floatํ ์ซ์ ํ๋๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๊ณ , Floatํ ์ซ์๋ฅผ ๋ฐํํ๋ค. ๋งค๊ฐ๋ณ์ Float๋ ์ค๋งํธํฐ ์ฌ์ฉ์๊ฐ ์ค์ ๋ก ํ๋ฉด์ ์๊ฐ๋ฝ์ ์ค์ ๋ก ๋ฌธ์ง๋ฅธ ๊ธธ์ด๊ฐ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐํํ๋ Float๋ 'ํธํฅ'์ํจ ์ ๋๋ค. ์ฌ์ฉ์์ ์ค์ ์คํฌ๋กค ๊ธธ์ด์ 30%๋ฅผ ์ญ๊ฐํด์ ๋ฒ๋ฆฌ๊ณ ์ถ์ ์ํฉ์ด๋ผ๊ณ ๊ฐ์ ํ๋ค. ์ด ๊ฒฝ์ฐ ์ฝ๋ฐฑ ํจ์๊ฐ 100.0F๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์๋ 30.0F์ ๋ฐํํ๊ฒ ๋ง๋๋ ์์ผ๋ก, ํ๋ก๊ทธ๋๋จธ๊ฐ ์ฌ์ฉ์์ ์ค์ ์คํฌ๋กค์ 'ํธํฅ'์ํฌ ์ ์๋ ๊ฒ์ด๋ค.
์ฃผ์ํ ์ ์, ๋ฐํ๋๋ Float๋ฅผ 30.0F์๋๋ผ ๋ฌด์ฌ์ฝ 70.0F๋ผ๊ณ ์ฐ์ง ์์์ผ ํ๋ค๋ ๊ฒ์ด๋ค. 'ํธํฅ์ด ๊ฐํด์ง ์๋ณธ'์ด ์๋๋ผ 'ํธํฅ์ํจ ์ ๋'๋ฅผ ๋ฐํํ๋ ๊ฒ์ด๋ค.
#3-5 ๋ฉ์๋ ์ฒด์ด๋ 1
์คํฌ๋กค์ด ๋๊ฒ ํ๋ฉด์ delta(์์ง์ธ ๊ฑฐ๋ฆฌ)๋ฅผ ์ถ์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น? ๋ฐ๋ก scrollable()๊ณผ verticalScroll() (๋๋ horizontalScroll())๋ฅผ ์ฐ๋ฌ์ ๋ฉ์๋ ์ฒด์ด๋ ํ๋ฉด ๋๋ค.
val scrollableState = rememberScrollableState { delta ->
println("delta: $delta") // ← ๋์ถฉ delta๋ฅผ ์ถ์ฒํ๋ ์ฝ๋๋ผ๊ณ ๊ฐ์ ํ๋ค
delta * 9 / 10 // ์ค์ ์คํฌ๋กค์ 90%๋ฅผ ์ญ๊ฐํ๋ค. ๊ต์ฅํ ๋๋ฆฌ๊ฒ ์คํฌ๋กค๋ ๊ฒ์ด๋ค.
}
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(
state = scrollState
)
.scrollable(
state = scrollableState,
orientation = Orientation.Vertical
)
) {
val textCount = 20
repeat(textCount) {
Text(
text = "(${it + 1} / ${textCount})",
fontSize = 32.sp,
)
Spacer(modifier = Modifier.height(24.dp))
}
}
์ฝ๋ฐฑ ํจ์๊ฐ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ delta์ 100%๊ฐ ์๋ 90% ์๋นํ๊ฒ ๋ง๋ค์๋ค. ์ฌ์ฉ์๋ ๊ฝค ํ๋ค ๊ฒ์ด๋ค. ์๋ํ๋ฉด ๊ฐ์ ์์ ์คํฌ๋กค ํ๊ธฐ ์ํด์ ํ์๋ณด๋ค ์๊ฐ๋ฝ์ 10๋ฐฐ๋ ๋ ์์ง์ฌ์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
#3-6 ๋ฉ์๋ ์ฒด์ด๋ 2
val scrollableState = rememberScrollableState { delta ->
println("delta: $delta") // ← ๋์ถฉ delta๋ฅผ ์ถ์ฒํ๋ ์ฝ๋๋ผ๊ณ ๊ฐ์ ํ๋ค
delta * 9 / 10 // ์ค์ ์คํฌ๋กค์ 90%๋ฅผ ์ญ๊ฐํ๋ค. ๊ต์ฅํ ๋๋ฆฌ๊ฒ ์คํฌ๋กค๋ ๊ฒ์ด๋ค.
}
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxWidth()
.scrollable(
state = scrollableState,
orientation = Orientation.Vertical
)
.verticalScroll(
state = scrollState
)
) {
val textCount = 20
repeat(textCount) {
Text(
text = "(${it + 1} / ${textCount})",
fontSize = 32.sp,
)
Spacer(modifier = Modifier.height(24.dp))
}
}
#3-5์ ๋ฉ์๋ ์ฒด์ด๋ ์์๋ฅผ ์ ์ธํ๋ฉด ์์ ํ ๋์ผํ ์ฝ๋๋ค. ํ์ง๋ง ์คํฌ๋กค์ด ํ๋ฒํ๊ฒ ์ ๋๋ค. ์๋ํ๋ฉด scrollableState์ ์ฝ๋ฐฑ ํจ์๊ฐ ์ ์ฉ๋์ง ์์๊ธฐ์ ๊ทธ๋ ๋ค. Modifier์์ ์ด๋ฒคํธ ์ ํ ๋ฐฉํฅ์ (๋ฉ์๋ ์ฒด์ด๋ ์์์) ์ญ๋ฐฉํฅ์ด๋ผ๋ ๊ฒ์ ๊ธฐ์ตํ์. ์ค์ ๋ก ์คํฌ๋กค์ด ๋๊ฒ ํ๋ verticalScroll() ์ ์ฅ์์๋ ํธํฅ๋๊ธฐ ์ ์ ์คํฌ๋กค ์ด๋๋(delta)์ ๋ฐ์๋ณธ ์ ์ด๋ ์คํฌ๋กค์ด ์ ์์ ์ผ๋ก ๋ฉ์ฉกํ ๋ผ๋ฒ๋ฆฐ ๊ฒ์ด๋ค.
#4 ์์ฝ
verticalScroll()๊ณผ scrollable() ๋ ๋ค ์ปดํฌ์ ๋ธ์ ์คํฌ๋กค ๊ฐ๋ฅ์ผ ๋ง๋ ๋ค. ๊ทธ๋ฌ๋, ์คํฌ๋กค ๋๊ฒ ๋ง๋๋ ๊ฑด verticalScroll() ๋ฟ์ด๋ค.
#5 ์ด์ด์ง๋ ๊ธ
[Android] Pointer input - Nested Scroll
#1 ์ด์ ๊ฒ์๊ธ [Android] Pointer input - Scroll#1 ๊ฐ์ ์คํฌ๋กค | Jetpack Compose | Android Developers์ด ํ์ด์ง๋ Cloud Translation API๋ฅผ ํตํด ๋ฒ์ญ๋์์ต๋๋ค. ์คํฌ๋กค ์ปฌ๋ ์ ์ ์ฌ์ฉํด ์ ๋ฆฌํ๊ธฐ ๋ด ํ๊ฒฝ์ค์
kenel.tistory.com
'๊นจ์ ๊ฐ๋ ๐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] App layout - ๊ธฐ์ด (0) | 2025.02.27 |
---|---|
[Android] Pointer input - Nested Scroll (0) | 2025.02.18 |
[Android] Pointer input - Gesture (0) | 2025.02.08 |
[Android] Pointer input - AwaitPointerEventScope()์ ๋ฉ์๋๋ค (0) | 2025.02.08 |
[Android] Pointer input - PointerInputChange, PointerEvent (0) | 2025.02.07 |