Android/Development Tips

확대, 축소, 이동, 회전 가능한 컴포즈 뷰

Nanamare 2022. 12. 30. 22:06
728x90
예시 영상은 티스토리 버그로 동영상 첨부가 안되어, 파일로 첨부합니다.

rotation disabled.mp4
10.51MB
rotation enabled.mp4
16.89MB

 

@Composable
fun ZoomableBox(
    modifier: Modifier = Modifier,
    enableRotation: Boolean = false,
    minScale: Float = 0.5f,
    maxScale: Float = 3f,
    content: @Composable ZoomableBoxScope.() -> Unit
) {
    var rotationZ by remember { mutableStateOf(0f) }
    var scale by remember { mutableStateOf(1f) }
    var offsetX by remember { mutableStateOf(0f) }
    var offsetY by remember { mutableStateOf(0f) }
    var size by remember { mutableStateOf(IntSize.Zero) }

    Box(
        modifier = modifier
            .clip(RectangleShape)
            .onSizeChanged { size = it }
            .pointerInput(Unit) {
                detectTransformGestures { _, pan, zoom, rotation ->
                    scale = maxOf(minScale, minOf(scale * zoom, maxScale))
                    if (scale > 1f) {
                        val maxX = (size.width * (scale - 1)) / 2
                        val minX = -maxX
                        offsetX = maxOf(minX, minOf(maxX, offsetX + pan.x))
                        val maxY = (size.height * (scale - 1)) / 2
                        val minY = -maxY
                        offsetY = maxOf(minY, minOf(maxY, offsetY + pan.y))
                    }
                    if (enableRotation) {
                        rotationZ += rotation
                    }
                }
            }
    ) {
        ZoomableBoxScopeImpl(scale, offsetX, offsetY, rotationZ).content()
    }
}

interface ZoomableBoxScope {
    val scale: Float
    val offsetX: Float
    val offsetY: Float
    val rotationZ: Float
}

private data class ZoomableBoxScopeImpl(
    override val scale: Float,
    override val offsetX: Float,
    override val offsetY: Float,
    override val rotationZ: Float
) : ZoomableBoxScope

사용 예시

ZoomableBox(enableRotation = true) {
    AsyncImage(
        contentScale = ContentScale.FillHeight,
        modifier = Modifier
            .fillMaxSize()
            .graphicsLayer(
                scaleX = scale,
                scaleY = scale,
                translationX = offsetX,
                translationY = offsetY,
                rotationZ = rotationZ
            ),
        model = "${BuildConfig.TMDB_IMAGE_ORIGINAL_URL}${movieImageModel.posters[page].filePath}",
        placeholder = rememberAsyncImagePainter(model = LoadingView(modifier = Modifier.fillMaxSize())),
        contentDescription = "DetailMovieImage"
    )
}

 

혹시나 필요하신 분이 계실까 싶어 올려둡니다 :)

그럼 20000!

 

https://github.com/Nanamare/MovieCompose/blob/main/app/src/main/java/com/nanamare/movie/ui/screen/DetailMovieScreen.kt#L94

 

GitHub - Nanamare/MovieCompose: Laboratory about Jetpack Compose

Laboratory about Jetpack Compose. Contribute to Nanamare/MovieCompose development by creating an account on GitHub.

github.com

 

728x90