Merge remote-tracking branch 'origin/master' into gpeal/leland-code-review
diff --git a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimation.kt b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimation.kt
index dc2cf2c..a84608e 100644
--- a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimation.kt
+++ b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimation.kt
@@ -2,23 +2,28 @@
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.aspectRatio
-import androidx.compose.runtime.*
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.dispatch.withFrameNanos
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.onCommit
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.drawscope.withTransform
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.platform.ContextAmbient
-import androidx.compose.ui.platform.LifecycleOwnerAmbient
-import androidx.lifecycle.DefaultLifecycleObserver
-import androidx.lifecycle.LifecycleOwner
-import java.util.concurrent.TimeUnit
-import androidx.compose.runtime.getValue
-import com.airbnb.lottie.*
+import com.airbnb.lottie.LottieComposition
+import com.airbnb.lottie.LottieCompositionFactory
+import com.airbnb.lottie.LottieDrawable
import com.airbnb.lottie.utils.Logger
import com.airbnb.lottie.utils.MiscUtils.lerp
import java.io.FileInputStream
+import java.util.concurrent.TimeUnit
import java.util.zip.ZipInputStream
import kotlin.math.floor
@@ -32,7 +37,7 @@
var result: LottieCompositionResult by remember { mutableStateOf(LottieCompositionResult.Loading) }
onCommit(spec) {
var isDisposed = false
- val task = when(spec) {
+ val task = when (spec) {
is LottieAnimationSpec.RawRes -> LottieCompositionFactory.fromRawRes(context, spec.resId)
is LottieAnimationSpec.Url -> LottieCompositionFactory.fromUrl(context, spec.url)
is LottieAnimationSpec.File -> {
@@ -82,26 +87,24 @@
fun LottieAnimation(
composition: LottieComposition?,
state: LottieAnimationState,
- modifier: Modifier = Modifier
+ modifier: Modifier = Modifier,
) {
val drawable = remember {
LottieDrawable().apply {
enableMergePathsForKitKatAndAbove(true)
}
}
- val isStarted by isStarted()
- val isPlaying = state.isPlaying && isStarted
- onCommit(composition) {
+ SideEffect {
drawable.composition = composition
}
// TODO: handle min/max frame setting
- LaunchedTask(composition, isPlaying) {
- if (!isPlaying || composition == null) return@LaunchedTask
+ LaunchedEffect(composition, state.isPlaying) {
+ if (!state.isPlaying || composition == null) return@LaunchedEffect
var repeatCount = 0
- if (isPlaying && state.progress == 1f) state.progress = 0f
+ if (state.isPlaying && state.progress == 1f) state.progress = 0f
var lastFrameTime = withFrameNanos { it }
while (true) {
withFrameNanos { frameTime ->
@@ -124,9 +127,7 @@
}
if (composition == null || composition.duration == 0f) return
- drawable.progress = state.progress
- drawable.setOutlineMasksAndMattes(state.outlineMasksAndMattes)
- drawable.isApplyingOpacityToLayersEnabled = state.applyOpacityToLayers
+ SideEffect {}
Canvas(
modifier = Modifier
@@ -134,6 +135,9 @@
.then(modifier)
) {
drawIntoCanvas { canvas ->
+ drawable.progress = state.progress
+ drawable.setOutlineMasksAndMattes(state.outlineMasksAndMattes)
+ drawable.isApplyingOpacityToLayersEnabled = state.applyOpacityToLayers
withTransform({
scale(size.width / composition.bounds.width().toFloat(), size.height / composition.bounds.height().toFloat(), Offset.Zero)
}) {
@@ -144,24 +148,6 @@
}
@Composable
-private fun isStarted(): State<Boolean> {
- val state = remember { mutableStateOf(false) }
- val lifecycleOwner = LifecycleOwnerAmbient.current
- onCommit(lifecycleOwner) {
- lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
- override fun onStart(owner: LifecycleOwner) {
- state.value = true
- }
-
- override fun onStop(owner: LifecycleOwner) {
- state.value = false
- }
- })
- }
- return state
-}
-
-@Composable
private fun Modifier.maintainAspectRatio(composition: LottieComposition?): Modifier {
composition ?: return this
return this.then(aspectRatio(composition.bounds.width() / composition.bounds.height().toFloat()))
diff --git a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimationState.kt b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimationState.kt
index 12386f7..a245789 100644
--- a/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimationState.kt
+++ b/lottie-compose/src/main/java/com/airbnb/lottie/compose/LottieAnimationState.kt
@@ -12,6 +12,7 @@
repeatCount: Int = 0,
initialProgress: Float = 0f,
): LottieAnimationState {
+ // Use rememberSavedInstanceState so you can pause/resume animations
return remember(repeatCount, autoPlay) {
LottieAnimationState(isPlaying = autoPlay, repeatCount, initialProgress)
}
@@ -27,6 +28,7 @@
) {
var progress by mutableStateOf(initialProgress)
+ // TODO: make this public
private var _frame = mutableStateOf(0)
val frame: Int by _frame