From 4b69bc1423e6423d7e5ddd4281c5ffef5b0e115f Mon Sep 17 00:00:00 2001 From: Jossi Wolf <10628007+jossiwolf@users.noreply.github.com> Date: Wed, 24 Feb 2021 17:16:00 +0100 Subject: [PATCH] [Compose] Add merge paths flag (#1744) Fixes #1734 LottieAnimationView had merge paths disabled by default, but LottieAnimation enables them by default. As long as merge paths contain known bugs, I think it makes sense not to change that behavior - what do you think? I added a flag for it to the state. If you want, we can add it as a constructor param too, but I feel like that's not needed as it's not that commonly used. --- CHANGELOG_COMPOSE.md | 3 ++ build.gradle | 2 +- .../airbnb/lottie/compose/LottieAnimation.kt | 11 ++--- .../lottie/compose/LottieAnimationState.kt | 46 ++++++++++++++++++- .../lottiefiles/LottieFilesSearchPage.kt | 3 +- .../sample/compose/player/PlayerPage.kt | 23 ++++++++-- .../sample/compose/player/ToolbarChip.kt | 9 ++-- .../src/main/res/values/strings.xml | 1 + 8 files changed, 77 insertions(+), 21 deletions(-) diff --git a/CHANGELOG_COMPOSE.md b/CHANGELOG_COMPOSE.md index 0e006170c6..90560778b3 100644 --- a/CHANGELOG_COMPOSE.md +++ b/CHANGELOG_COMPOSE.md @@ -1,6 +1,9 @@ #### Note: For the time being, we won't provide numbered releases for every new Jetpack Compose version. Check out our [snapshot builds](https://github.com/airbnb/lottie/blob/master/android-compose.md#getting-started) instead. +# 1.0.0-alpha07-SNAPSHOT +* Add flag for merge paths to LottieAnimationState + # 1.0.0-alpha06 * Compatible with Jetpack Compose Alpha 12 diff --git a/build.gradle b/build.gradle index a1809233e5..b35e69293e 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { } dependencies { classpath 'org.ajoberstar:grgit:1.9.3' - classpath 'com.android.tools.build:gradle:7.0.0-alpha06' + classpath 'com.android.tools.build:gradle:7.0.0-alpha07' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlinVersion" classpath 'org.ajoberstar:grgit:1.9.3' 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 1c7a10a0a8..61b3473d40 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 @@ -9,7 +9,6 @@ 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.AmbientContext import androidx.compose.ui.platform.LocalContext import com.airbnb.lottie.LottieComposition import com.airbnb.lottie.LottieCompositionFactory @@ -80,11 +79,7 @@ fun LottieAnimation( state: LottieAnimationState, modifier: Modifier = Modifier, ) { - val drawable = remember { - LottieDrawable().apply { - enableMergePathsForKitKatAndAbove(true) - } - } + val drawable = remember { LottieDrawable() } SideEffect { drawable.composition = composition @@ -118,7 +113,6 @@ fun LottieAnimation( } if (composition == null || composition.duration == 0f) return - SideEffect {} Canvas( modifier = Modifier @@ -129,6 +123,7 @@ fun LottieAnimation( drawable.progress = state.progress drawable.setOutlineMasksAndMattes(state.outlineMasksAndMattes) drawable.isApplyingOpacityToLayersEnabled = state.applyOpacityToLayers + drawable.enableMergePathsForKitKatAndAbove(state.enableMergePaths) withTransform({ scale(size.width / composition.bounds.width().toFloat(), size.height / composition.bounds.height().toFloat(), Offset.Zero) }) { @@ -143,4 +138,4 @@ private fun Modifier.maintainAspectRatio(composition: LottieComposition?): Modif return this.then(aspectRatio(composition.bounds.width() / composition.bounds.height().toFloat())) } -private fun lerp(a: Float, b: Float, @FloatRange(from = 0.0, to = 1.0) percentage: Float) = a + percentage * (b - a) +private fun lerp(a: Float, b: Float, @FloatRange(from = 0.0, to = 1.0) percentage: Float) = a + percentage * (b - a) 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 a2457895e5..b410285e43 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 @@ -6,25 +6,47 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +/** + * Create a [LottieAnimationState] and remember it + * + * @param autoPlay Initial value for [LottieAnimationState.isPlaying] + * @param repeatCount Initial value for [LottieAnimationState.repeatCount] + * @param initialProgress Initial value for [LottieAnimationState.progress] + * @param enableMergePaths Initial value for [LottieAnimationState.enableMergePaths] + */ @Composable fun rememberLottieAnimationState( autoPlay: Boolean = true, repeatCount: Int = 0, initialProgress: Float = 0f, + enableMergePaths: Boolean = true ): LottieAnimationState { // Use rememberSavedInstanceState so you can pause/resume animations return remember(repeatCount, autoPlay) { - LottieAnimationState(isPlaying = autoPlay, repeatCount, initialProgress) + LottieAnimationState( + isPlaying = autoPlay, + repeatCount = repeatCount, + initialProgress = initialProgress, + enableMergePaths = enableMergePaths + ) } } /** - * @see rememberLottieAnimationState() + * State of the [LottieAnimation] composable + * + * @param isPlaying Initial value for [isPlaying] + * @param repeatCount Initial value for [repeatCount] + * @param initialProgress Initial value for [progress] + * @param enableMergePaths Initial value for [enableMergePaths] + * + * @see rememberLottieAnimationState */ class LottieAnimationState( isPlaying: Boolean, repeatCount: Int = 0, initialProgress: Float = 0f, + enableMergePaths: Boolean = true ) { var progress by mutableStateOf(initialProgress) @@ -32,7 +54,15 @@ class LottieAnimationState( private var _frame = mutableStateOf(0) val frame: Int by _frame + /** + * Whether the animation is currently playing. + */ var isPlaying by mutableStateOf(isPlaying) + + /** + * How many times the animation will be played. Use [Int.MAX_VALUE] for + * infinite repetitions. + */ var repeatCount by mutableStateOf(repeatCount) var speed by mutableStateOf(1f) @@ -58,6 +88,18 @@ class LottieAnimationState( */ var applyOpacityToLayers by mutableStateOf(false) + /** + * Enable this to get merge path support. + *
+ * Merge paths currently don't work if the the operand shape is entirely contained within the + * first shape. If you need to cut out one shape from another shape, use an even-odd fill type + * instead of using merge paths. + *
+ * If your animation contains merge paths and you are encountering rendering issues, disabling
+ * merge paths might help.
+ */
+ var enableMergePaths by mutableStateOf(enableMergePaths)
+
internal fun updateFrame(frame: Int) {
_frame.value = frame
}
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/lottiefiles/LottieFilesSearchPage.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/lottiefiles/LottieFilesSearchPage.kt
index 37e48e2859..4933326d19 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/lottiefiles/LottieFilesSearchPage.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/lottiefiles/LottieFilesSearchPage.kt
@@ -141,7 +141,8 @@ fun LottieFilesSearchPage(
value = state.query,
onValueChange = onQueryChanged,
label = { Text(stringResource(R.string.query)) },
- modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
+ singleLine = true
)
LazyColumn(
modifier = Modifier.weight(1f)
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/player/PlayerPage.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/player/PlayerPage.kt
index a8c81f4432..f882c0147a 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/player/PlayerPage.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/player/PlayerPage.kt
@@ -19,7 +19,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
@@ -50,6 +52,7 @@ fun PlayerPage(
val scaffoldState = rememberScaffoldState()
val outlineMasksAndMattes = remember { mutableStateOf(false) }
val applyOpacityToLayers = remember { mutableStateOf(false) }
+ val enableMergePaths = remember { mutableStateOf(animationState.enableMergePaths) }
var focusMode by remember { mutableStateOf(false) }
var backgroundColor by remember { mutableStateOf(animationBackgroundColor) }
var showWarningsDialog by remember { mutableStateOf(false) }
@@ -72,6 +75,7 @@ fun PlayerPage(
animationState.outlineMasksAndMattes = outlineMasksAndMattes.value
animationState.applyOpacityToLayers = applyOpacityToLayers.value
+ animationState.enableMergePaths = enableMergePaths.value
Scaffold(
scaffoldState = scaffoldState,
@@ -164,6 +168,7 @@ fun PlayerPage(
backgroundColor = backgroundColorToolbar,
outlineMasksAndMattes = outlineMasksAndMattes,
applyOpacityToLayers = applyOpacityToLayers,
+ enableMergePaths = enableMergePaths
)
}
}
@@ -344,6 +349,7 @@ private fun Toolbar(
backgroundColor: MutableState