Jetpack Compose์์ pager๋ฅผ ๊ตฌํํด๋ณด์
์ฝ์ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค.
// coil
implementation("io.coil-kt:coil-compose:2.4.0")
๊ฐ๋จํ๊ฒ ํ์ด์ ์ ๋ค์ด๊ฐ ์ด๋ฏธ์ง๋ฅผ list๋ก ๋ง๋ค์ด๋์.
val images = remember {
mutableStateListOf(
"https://images.unsplash.com/photo-1694481348806-0b6de4934812?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1471&q=80",
"https://images.unsplash.com/photo-1694057442309-bfe467bff9a9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80",
"https://images.unsplash.com/photo-1559803509-40f78353d413?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2564&q=80",
"https://plus.unsplash.com/premium_photo-1668633086435-a16be494a922?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80"
)
}
๋๋ unsplash์์ ์ด๋ฏธ์ง ์ฃผ์ ๋ณต์ฌ๋ฅผ ํด์ ํด๋น ์ด๋ฏธ์ง๋ฅผ ๋ฟ๋ ค์ฃผ๋ ๋ฐฉ์์ผ๋ก ์ฑํํ๋ค.
๊ทธ๋์ ๋ณด์ฌ์ง ์ด๋ฏธ์ง๋ค์ ๋จผ์ ๋ฆฌ์คํธ๋ก ๋ง๋ค์ด์ฃผ๊ณ
๋ค์์ ํ์ด์ ์ ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์๋ pagerState
๋ฅผ ๋ง๋ค์ด์ค๋ค.
์ด์ Pager๊ฐ ๋ณด์ฌ์ง ๋ทฐ๋ฅผ Scaffold์ ๊ตฌํ๋ง ํด์ฃผ๋ฉด ๋์ด๋ค.
์ฝ๋
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainScreen() {
val images = remember {
mutableStateListOf(
"https://images.unsplash.com/photo-1694481348806-0b6de4934812?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1471&q=80",
"https://images.unsplash.com/photo-1694057442309-bfe467bff9a9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80",
"https://images.unsplash.com/photo-1559803509-40f78353d413?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2564&q=80",
"https://plus.unsplash.com/premium_photo-1668633086435-a16be494a922?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80"
)
}
val pagerState = rememberPagerState()
Scaffold(modifier = Modifier.padding(vertical = 48.dp)) {
HorizontalPager(pageCount = images.size, state = pagerState) { idx ->
AsyncImage(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
.clip(RoundedCornerShape(16.dp)),
model = ImageRequest.Builder(LocalContext.current).data(images[idx])
.build(),
contentDescription = "imagePager",
contentScale = ContentScale.Crop
)
}
}
} // End of MainScreen()
์ฌ๊ธฐ์ ํ์ด์ ์ ๊ฐ๋จํ ์ ๋๋ฉ์ด์ ์ ์ถ๊ฐํด๋ณด์
val pageOffset = (pagerState.currentPage - idx) + pagerState.currentPageOffsetFraction
val imageSize by animateFloatAsState(
targetValue = if (pageOffset != 0.0f) 0.75f else 1f,
animationSpec = tween(durationMillis = 300)
)
...
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
.clip(RoundedCornerShape(16.dp))
.graphicsLayer {
scaleX = imageSize
scaleY = imageSize
},
ํด๋น ๋ถ๋ถ์ ์ถ๊ฐํด์ฃผ๋ฉด ํ์ด์ ์์ ์ด๋ฏธ์ง x๊ฐ์ด 0.0์ด ์๋๊ฒฝ์ฐ์ 0.75๋ก ์์์ง๋ฉด์, 0.0f ์ผ๋๋ง ์ปค์ง๊ฒ ๋๋ค.
import android.annotation.SuppressLint
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Scaffold
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainScreen() {
val images = remember {
mutableStateListOf(
"https://images.unsplash.com/photo-1694481348806-0b6de4934812?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1471&q=80",
"https://images.unsplash.com/photo-1694057442309-bfe467bff9a9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80",
"https://images.unsplash.com/photo-1559803509-40f78353d413?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2564&q=80",
"https://plus.unsplash.com/premium_photo-1668633086435-a16be494a922?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80"
)
}
val pagerState = rememberPagerState()
val matrix = remember {
ColorMatrix()
}
Scaffold(modifier = Modifier.padding(vertical = 48.dp)) {
HorizontalPager(
pageCount = images.size, state = pagerState
) { idx ->
val pageOffset = (pagerState.currentPage - idx) + pagerState.currentPageOffsetFraction
val imageSize by animateFloatAsState(
targetValue = if (pageOffset != 0.0f) 0.75f else 1f,
animationSpec = tween(durationMillis = 300)
)
LaunchedEffect(key1 = imageSize) {
if (pageOffset != 0.0f) {
matrix.setToSaturation(0.0f)
} else {
matrix.setToSaturation(1f)
}
}
AsyncImage(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
.clip(RoundedCornerShape(16.dp))
.graphicsLayer {
scaleX = imageSize
scaleY = imageSize
},
model = ImageRequest.Builder(LocalContext.current).data(images[idx]).build(),
contentDescription = "imagePager",
contentScale = ContentScale.Crop,
colorFilter = ColorFilter.colorMatrix(matrix)
)
}
}
} // End of MainScreen()