Created
July 3, 2021 03:00
-
-
Save alashow/6492f6407434ca42ad7819dde2ae4a8e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2021, Alashov Berkeli | |
* All rights reserved. | |
*/ | |
package tm.alashow.common.compose.ui | |
import androidx.compose.animation.core.Animatable | |
import androidx.compose.foundation.gestures.detectTransformGestures | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.rememberCoroutineScope | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.graphics.graphicsLayer | |
import androidx.compose.ui.input.pointer.pointerInput | |
import kotlinx.coroutines.Job | |
import kotlinx.coroutines.delay | |
import kotlinx.coroutines.launch | |
/** | |
* Makes given [content] zoomable, optionally snaps back when [snapBack] is true. | |
*/ | |
@Composable | |
fun Zoomable( | |
maxScale: Float = 4f, | |
minScale: Float = 0.7f, | |
snapBack: Boolean = true, | |
modifier: Modifier = Modifier, | |
content: @Composable () -> Unit | |
) { | |
val coroutineScope = rememberCoroutineScope() | |
val scale = remember { Animatable(1f) } | |
val rotation = remember { Animatable(0f) } | |
val panX = remember { Animatable(0f) } | |
val panY = remember { Animatable(0f) } | |
var snapBackJob: Job? = null | |
Box( | |
modifier = modifier | |
.pointerInput(Unit) { | |
detectTransformGestures(false) { _, pan, zoomChange, rotationChange -> | |
coroutineScope.launch { | |
scale.snapTo(zoomChange.coerceIn(minScale, maxScale)) | |
rotation.snapTo(rotation.value + rotationChange) | |
panX.snapTo(panX.value + pan.x) | |
panY.snapTo(panY.value + pan.y) | |
if (snapBack) { | |
snapBackJob?.cancel() | |
snapBackJob = launch { | |
delay(150) | |
launch { scale.animateTo(1f) } | |
launch { rotation.animateTo(0f) } | |
launch { panX.animateTo(0f) } | |
launch { panY.animateTo(0f) } | |
} | |
} | |
} | |
} | |
} | |
.graphicsLayer( | |
scaleX = scale.value, | |
scaleY = scale.value, | |
translationX = panX.value, | |
translationY = panY.value, | |
rotationZ = rotation.value | |
) | |
) { | |
content() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment