Use Modifier.graphicsLayer for the animation

This commit is contained in:
Pierre-Yves Nicolas
2025-06-25 21:22:57 +02:00
parent 802bf20f08
commit 5cfe6244d3

View File

@@ -19,7 +19,6 @@ import android.graphics.BitmapFactory
import android.util.Log
import androidx.camera.core.ImageProxy
import androidx.camera.view.PreviewView
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
@@ -36,7 +35,6 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -54,15 +52,16 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalConfiguration
@@ -201,23 +200,22 @@ private fun CapturedImage(cameraUiState: CameraUiState, thumbnailCoords: Mutable
}
val transition = updateTransition(targetState = isAnimating, label = "captureAnimation")
val density = LocalDensity.current
var targetOffsetX by remember { mutableStateOf(0.dp) }
var targetOffsetY by remember { mutableStateOf(0.dp) }
var targetOffsetX by remember { mutableFloatStateOf(0f) }
var targetOffsetY by remember { mutableFloatStateOf(0f) }
val offsetX by transition.animateDp(
val offsetX by transition.animateFloat(
transitionSpec = { tween(durationMillis = ANIMATION_DURATION) },
label = "offsetX"
) { if (it) targetOffsetX else 0.dp }
val offsetY by transition.animateDp(
) { if (it) targetOffsetX else 0f }
val offsetY by transition.animateFloat(
transitionSpec = { tween(durationMillis = ANIMATION_DURATION) },
label = "offsetY"
) { if (it) targetOffsetY else 0.dp }
) { if (it) targetOffsetY else 0f }
val scale by transition.animateFloat(
transitionSpec = { tween(durationMillis = ANIMATION_DURATION) },
label = "scale"
) { if (it) 0.3f else 1f }
val justABitToTheTop = 100.dp
Box (modifier = Modifier
.onGloballyPositioned { coordinates ->
@@ -225,8 +223,8 @@ private fun CapturedImage(cameraUiState: CameraUiState, thumbnailCoords: Mutable
val centerX = bounds.left + bounds.width / 2
val centerY = bounds.top + bounds.height / 2
with(density) {
targetOffsetX = thumbnailCoords.value.x.toDp() - centerX.toDp() + PAGE_LIST_ELEMENT_SIZE_DP.dp
targetOffsetY = thumbnailCoords.value.y.toDp() - centerY.toDp() + justABitToTheTop
targetOffsetX = thumbnailCoords.value.x - centerX + PAGE_LIST_ELEMENT_SIZE_DP.dp.toPx()
targetOffsetY = thumbnailCoords.value.y - centerY + justABitToTheTop.toPx()
}
}
) {
@@ -236,8 +234,12 @@ private fun CapturedImage(cameraUiState: CameraUiState, thumbnailCoords: Mutable
modifier = Modifier
.fillMaxSize()
.padding(24.dp)
.offset(x = offsetX, y = offsetY - justABitToTheTop)
.scale(scale)
.graphicsLayer {
translationX = offsetX
translationY = offsetY - justABitToTheTop.toPx()
scaleX = scale
scaleY = scale
}
)
}
}