[Compose] Added more functionality to the player and sample (#1670)
Added apply opacity to layers, outline masks and mattes, and enabled merge paths by default. Also fixed some bugs in the sample app and added the ability load a file from a url.
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 5a457bf..189f87c 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
@@ -84,7 +84,11 @@
state: LottieAnimationState,
modifier: Modifier = Modifier
) {
- val drawable = remember { LottieDrawable() }
+ val drawable = remember {
+ LottieDrawable().apply {
+ enableMergePathsForKitKatAndAbove(true)
+ }
+ }
val isStarted by isStarted()
val isPlaying = state.isPlaying && isStarted
@@ -121,6 +125,8 @@
if (composition == null || composition.duration == 0f) return
drawable.progress = state.progress
+ drawable.setOutlineMasksAndMattes(state.outlineMasksAndMattes)
+ drawable.isApplyingOpacityToLayersEnabled = state.applyOpacityToLayers
Canvas(
modifier = Modifier
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 32964da..12386f7 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
@@ -35,6 +35,27 @@
var speed by mutableStateOf(1f)
+ /**
+ * Enable this to debug slow animations by outlining masks and mattes. The performance overhead of the masks and mattes will
+ * be proportional to the surface area of all of the masks/mattes combined.
+ * <p>
+ * DO NOT leave this enabled in production.
+ */
+ var outlineMasksAndMattes by mutableStateOf(false)
+
+
+ /**
+ * Sets whether to apply opacity to the each layer instead of shape.
+ * <p>
+ * Opacity is normally applied directly to a shape. In cases where translucent shapes overlap, applying opacity to a layer will be more accurate
+ * at the expense of performance.
+ * <p>
+ * The default value is false.
+ * <p>
+ * Note: This process is very expensive and will incur additional performance overhead.
+ */
+ var applyOpacityToLayers by mutableStateOf(false)
+
internal fun updateFrame(frame: Int) {
_frame.value = frame
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
index ee145cc..9364c21 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieDrawable.java
@@ -257,7 +257,10 @@
*
* DO NOT leave this enabled in production.
*/
- void setOutlineMasksAndMattes(boolean outline) {
+ public void setOutlineMasksAndMattes(boolean outline) {
+ if (outlineMasksAndMattes == outline) {
+ return;
+ }
outlineMasksAndMattes = outline;
if (compositionLayer != null) {
compositionLayer.setOutlineMasksAndMattes(outline);
diff --git a/sample-compose/build.gradle b/sample-compose/build.gradle
index bcf8d44..2374a1a 100644
--- a/sample-compose/build.gradle
+++ b/sample-compose/build.gradle
@@ -14,7 +14,7 @@
minSdkVersion 21
targetSdkVersion 30
versionCode 1
- versionName "1.0"
+ versionName VERSION_NAME
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ComposeActivity.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ComposeActivity.kt
index 543c0c7..5db00fb 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ComposeActivity.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ComposeActivity.kt
@@ -37,6 +37,7 @@
import com.airbnb.lottie.sample.compose.ui.Teal
import com.airbnb.lottie.sample.compose.ui.toColorSafe
import com.airbnb.lottie.sample.compose.utils.NavControllerAmbient
+import com.airbnb.lottie.sample.compose.utils.drawTopBorder
import com.airbnb.lottie.sample.compose.utils.getBase64String
class ComposeActivity : AppCompatActivity() {
@@ -96,12 +97,12 @@
) { entry ->
val arguments = entry.arguments ?: error("No arguments provided to ${Route.Player}")
val spec = when {
- arguments.containsKey("url") -> LottieAnimationSpec.Url(arguments.getBase64String("url") ?: error("url must be a string"))
- arguments.containsKey("file") -> LottieAnimationSpec.File(arguments.getBase64String("file") ?: error("file must be a string"))
- arguments.containsKey("asset") -> LottieAnimationSpec.Asset(arguments.getBase64String("asset") ?: error("asset must be a string"))
+ arguments.getString("url") != null -> LottieAnimationSpec.Url(arguments.getBase64String("url"))
+ arguments.getString("file") != null -> LottieAnimationSpec.File(arguments.getBase64String("file"))
+ arguments.getString("asset") != null -> LottieAnimationSpec.Asset(arguments.getBase64String("asset"))
else -> error("You must specify a url, file, or asset")
}
- val backgroundColor = when (arguments.containsKey("backgroundColor")) {
+ val backgroundColor = when (arguments.getString("backgroundColor") != null) {
true -> arguments.getBase64String("backgroundColor").toColorSafe()
else -> null
}
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/Route.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/Route.kt
index 96bab82..68212c5 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/Route.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/Route.kt
@@ -37,14 +37,14 @@
) {
val fullRoute = "$route?url={url}&file={file}&asset={asset}&backgroundColor={backgroundColor}"
- fun forUrl(url: String, backgroundColor: String?) = when (backgroundColor) {
+ fun forUrl(url: String, backgroundColor: String? = null) = when (backgroundColor) {
null -> "${route}?url=${url.toBase64()}"
else -> "${route}?url=${url.toBase64()}&backgroundColor=${backgroundColor.toBase64()}"
}
- fun forFile(file: String) = "${route}?file=$file"
+ fun forFile(file: String) = "${route}?file=${file.toBase64()}"
- fun forAsset(asset: String) = "${route}?asset=$asset"
+ fun forAsset(asset: String) = "${route}?asset=${asset.toBase64()}"
}
}
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/composables/AnimationRow.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/composables/AnimationRow.kt
index 34ed88d..2fd3bb6 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/composables/AnimationRow.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/composables/AnimationRow.kt
@@ -32,7 +32,7 @@
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
- .padding(8.dp)
+ .padding(16.dp)
.fillMaxWidth()
) {
CoilImage(
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 f0ca565..1120a94 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
@@ -9,6 +9,7 @@
import androidx.compose.foundation.lazy.LazyColumnForIndexed
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Icon
+import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Surface
import androidx.compose.material.TextField
import androidx.compose.material.icons.Icons
@@ -18,9 +19,11 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.compose.navigate
import androidx.ui.tooling.preview.Preview
+import com.airbnb.lottie.sample.compose.R
import com.airbnb.lottie.sample.compose.Route
import com.airbnb.lottie.sample.compose.api.AnimationDataV2
import com.airbnb.lottie.sample.compose.api.LottieFilesApi
@@ -38,7 +41,7 @@
import kotlinx.coroutines.launch
data class LottieFilesSearchState(
- val query: String = "Loading",
+ val query: String = "",
val results: List<AnimationDataV2> = emptyList(),
val currentPage: Int = 1,
val lastPage: Int = 0,
@@ -125,7 +128,7 @@
@Composable
fun LottieFilesSearchPage(
state: LottieFilesSearchState,
- setQuery: (String) -> Unit,
+ onQueryChanged: (String) -> Unit,
fetchNextPage: () -> Unit,
onAnimationClicked: (AnimationDataV2) -> Unit,
modifier: Modifier = Modifier,
@@ -134,11 +137,11 @@
Column(
modifier = Modifier.then(modifier)
) {
- TextField(
+ OutlinedTextField(
value = state.query,
- onValueChange = { query -> setQuery(query) },
- label = { Text("Query") },
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ onValueChange = onQueryChanged,
+ label = { Text(stringResource(R.string.query)) },
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
LazyColumnForIndexed(
state.results,
@@ -182,7 +185,7 @@
Surface(color = Color.White) {
LottieFilesSearchPage(
state = state,
- setQuery = {},
+ onQueryChanged = {},
fetchNextPage = {},
onAnimationClicked = {}
)
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 2246bfb..3e71a6f 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
@@ -1,5 +1,6 @@
package com.airbnb.lottie.sample.compose.player
+import android.os.Build
import androidx.activity.OnBackPressedDispatcher
import androidx.compose.foundation.ScrollableColumn
import androidx.compose.foundation.ScrollableRow
@@ -32,6 +33,7 @@
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.RemoveRedEye
import androidx.compose.material.icons.filled.Repeat
+import androidx.compose.material.icons.filled.Warning
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedTask
@@ -39,6 +41,7 @@
import androidx.compose.runtime.Providers
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.Alignment
@@ -61,6 +64,7 @@
import com.airbnb.lottie.compose.rememberLottieAnimationState
import com.airbnb.lottie.compose.rememberLottieComposition
import com.airbnb.lottie.sample.compose.BackPressedDispatcherAmbient
+import com.airbnb.lottie.sample.compose.BuildConfig
import com.airbnb.lottie.sample.compose.R
import com.airbnb.lottie.sample.compose.composables.DebouncedCircularProgressIndicator
import com.airbnb.lottie.sample.compose.composables.SeekBar
@@ -68,7 +72,6 @@
import com.airbnb.lottie.sample.compose.utils.drawTopBorder
import com.airbnb.lottie.sample.compose.utils.maybeBackground
import com.airbnb.lottie.sample.compose.utils.maybeDrawBorder
-import com.airbnb.lottie.sample.compose.utils.quantityStringResource
import kotlin.math.ceil
import kotlin.math.roundToInt
@@ -81,8 +84,11 @@
val compositionResult = rememberLottieComposition(spec)
val animationState = rememberLottieAnimationState(autoPlay = true, repeatCount = Integer.MAX_VALUE)
val scaffoldState = rememberScaffoldState()
+ val outlineMasksAndMattes = remember { mutableStateOf(false) }
+ val applyOpacityToLayers = remember { mutableStateOf(false) }
var focusMode by remember { mutableStateOf(false) }
var backgroundColor by remember { mutableStateOf(animationBackgroundColor) }
+ var showWarningsDialog by remember { mutableStateOf(false) }
val borderToolbar = remember { mutableStateOf(false) }
val speedToolbar = remember { mutableStateOf(false) }
@@ -100,6 +106,13 @@
}
}
+ onCommit(outlineMasksAndMattes.value) {
+ animationState.outlineMasksAndMattes = outlineMasksAndMattes.value
+ }
+ onCommit(applyOpacityToLayers.value) {
+ animationState.applyOpacityToLayers = applyOpacityToLayers.value
+ }
+
Scaffold(
scaffoldState = scaffoldState,
topBar = {
@@ -115,6 +128,16 @@
}
},
actions = {
+ if (compositionResult()?.warnings?.isNotEmpty() == true) {
+ IconButton(
+ onClick = { showWarningsDialog = true }
+ ) {
+ Icon(
+ Icons.Filled.Warning,
+ tint = Color.Black,
+ )
+ }
+ }
IconButton(
onClick = { focusMode = !focusMode },
) {
@@ -172,11 +195,16 @@
border = borderToolbar,
speed = speedToolbar,
backgroundColor = backgroundColorToolbar,
- warnings = compositionResult()?.warnings ?: emptyList()
+ outlineMasksAndMattes = outlineMasksAndMattes,
+ applyOpacityToLayers = applyOpacityToLayers,
)
}
}
}
+
+ if (showWarningsDialog) {
+ WarningDialog(warnings = compositionResult()?.warnings ?: emptyList(), onDismiss = { showWarningsDialog = false })
+ }
}
@Composable
@@ -190,43 +218,56 @@
val progress = (totalTime / 100.0) * ((animationState.progress * 100.0).roundToInt())
val progressFormatted = ("%.1f").format(progress)
- Row(
- verticalAlignment = Alignment.CenterVertically,
+ Box(
modifier = Modifier
- .drawTopBorder()
+ .fillMaxWidth()
) {
- Box(
- alignment = Alignment.Center
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .drawTopBorder()
) {
- IconButton(
- onClick = { animationState.toggleIsPlaying() },
+ Box(
+ alignment = Alignment.Center
) {
- Icon(if (animationState.isPlaying) Icons.Filled.Pause else Icons.Filled.PlayArrow)
+ IconButton(
+ onClick = { animationState.toggleIsPlaying() },
+ ) {
+ Icon(if (animationState.isPlaying) Icons.Filled.Pause else Icons.Filled.PlayArrow)
+ }
+ Text(
+ "${animationState.frame}/${ceil(composition?.durationFrames ?: 0f).toInt()}\n${progressFormatted}/$totalTimeFormatted",
+ style = TextStyle(fontSize = 8.sp),
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .padding(top = 48.dp, bottom = 8.dp)
+ )
}
- Text(
- "${animationState.frame}/${ceil(composition?.durationFrames ?: 0f).toInt()}\n${progressFormatted}/$totalTimeFormatted",
- style = TextStyle(fontSize = 8.sp),
- textAlign = TextAlign.Center,
- modifier = Modifier
- .padding(top = 48.dp, bottom = 8.dp)
+ SeekBar(
+ progress = animationState.progress,
+ onProgressChanged = {
+ animationState.progress = it
+ },
+ modifier = Modifier.weight(1f)
)
+ IconButton(onClick = {
+ val repeatCount = if (animationState.repeatCount == Integer.MAX_VALUE) 0 else Integer.MAX_VALUE
+ animationState.repeatCount = repeatCount
+ }) {
+ Icon(
+ Icons.Filled.Repeat,
+ tint = if (animationState.repeatCount > 0) Teal else Color.Black,
+ )
+ }
}
- SeekBar(
- progress = animationState.progress,
- onProgressChanged = {
- animationState.progress = it
- },
- modifier = Modifier.weight(1f)
+ Text(
+ BuildConfig.VERSION_NAME,
+ fontSize = 6.sp,
+ color = Color.Gray,
+ modifier = Modifier
+ .align(Alignment.BottomCenter)
+ .padding(bottom = 12.dp)
)
- IconButton(onClick = {
- val repeatCount = if (animationState.repeatCount == Integer.MAX_VALUE) 0 else Integer.MAX_VALUE
- animationState.repeatCount = repeatCount
- }) {
- Icon(
- Icons.Filled.Repeat,
- tint = if (animationState.repeatCount > 0) Teal else Color.Black,
- )
- }
}
}
@@ -321,34 +362,34 @@
border: MutableState<Boolean>,
speed: MutableState<Boolean>,
backgroundColor: MutableState<Boolean>,
- warnings: List<String>,
+ outlineMasksAndMattes: MutableState<Boolean>,
+ applyOpacityToLayers: MutableState<Boolean>,
) {
- var showWarningsDialog by remember { mutableStateOf(false) }
-
- if (showWarningsDialog) {
- WarningDialog(warnings = warnings, onDismiss = { showWarningsDialog = false })
- }
-
ScrollableRow(
contentPadding = PaddingValues(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp),
modifier = Modifier
.drawTopBorder()
.fillMaxWidth()
) {
- if (warnings.isNotEmpty()) {
- ToolbarChip(
- iconRes = R.drawable.ic_warning,
- label = quantityStringResource(R.plurals.toolbar_item_warning, warnings.size, warnings.size),
- isActivated = true,
- onClick = { showWarningsDialog = true },
- modifier = Modifier.padding(end = 8.dp)
- )
- }
ToolbarChip(
- iconRes = R.drawable.ic_border,
- label = stringResource(R.string.toolbar_item_border),
- isActivated = border.value,
- onClick = { border.value = it },
+ iconRes = R.drawable.ic_masks_and_mattes,
+ label = stringResource(R.string.toolbar_item_masks),
+ isActivated = outlineMasksAndMattes.value,
+ onClick = { outlineMasksAndMattes.value = it },
+ modifier = Modifier.padding(end = 8.dp)
+ )
+ ToolbarChip(
+ iconRes = R.drawable.ic_layers,
+ label = stringResource(R.string.toolbar_item_opacity_layers),
+ isActivated = applyOpacityToLayers.value,
+ onClick = { applyOpacityToLayers.value = it },
+ modifier = Modifier.padding(end = 8.dp)
+ )
+ ToolbarChip(
+ iconRes = R.drawable.ic_color,
+ label = stringResource(R.string.toolbar_item_color),
+ isActivated = backgroundColor.value,
+ onClick = { backgroundColor.value = it },
modifier = Modifier.padding(end = 8.dp)
)
ToolbarChip(
@@ -359,10 +400,10 @@
modifier = Modifier.padding(end = 8.dp)
)
ToolbarChip(
- iconRes = R.drawable.ic_color,
- label = stringResource(R.string.toolbar_item_color),
- isActivated = backgroundColor.value,
- onClick = { backgroundColor.value = it },
+ iconRes = R.drawable.ic_border,
+ label = stringResource(R.string.toolbar_item_border),
+ isActivated = border.value,
+ onClick = { border.value = it },
modifier = Modifier.padding(end = 8.dp)
)
}
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/preview/PreviewPage.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/preview/PreviewPage.kt
index 6b4e27f..40b86e1 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/preview/PreviewPage.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/preview/PreviewPage.kt
@@ -14,7 +14,9 @@
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.Icon
+import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Surface
+import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -27,7 +29,9 @@
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
+import androidx.navigation.compose.navArgument
import androidx.ui.tooling.preview.Preview
import com.airbnb.lottie.sample.compose.R
import com.airbnb.lottie.sample.compose.Route
@@ -39,6 +43,7 @@
@Composable
fun PreviewPage() {
var showingAssetsDialog by remember { mutableStateOf(false) }
+ var showingUrlDialog by remember { mutableStateOf(false) }
val navController = findNavController()
Column {
@@ -50,7 +55,7 @@
}
PreviewRow(R.drawable.ic_network, R.string.enter_url) {
-
+ showingUrlDialog = true
}
PreviewRow(R.drawable.ic_storage, R.string.load_from_assets) {
showingAssetsDialog = true
@@ -64,13 +69,20 @@
navController.navigate(Route.Player.forAsset(assetName))
}
)
+ UrlDialog(
+ showingUrlDialog,
+ onDismiss = { showingUrlDialog = false },
+ onUrlSelected = { url ->
+ navController.navigate(Route.Player.forUrl(url))
+ }
+ )
}
@Composable
private fun PreviewRow(
@DrawableRes iconRes: Int,
@StringRes textRes: Int,
- onClick: () -> Unit
+ onClick: () -> Unit,
) {
Surface(
modifier = Modifier.clickable(onClick = onClick)
@@ -109,7 +121,6 @@
Dialog(onDismissRequest = onDismiss) {
Surface(
shape = RoundedCornerShape(4.dp),
-
) {
Column(
modifier = Modifier
@@ -127,6 +138,40 @@
}
@Composable
+fun UrlDialog(isShowing: Boolean, onDismiss: () -> Unit, onUrlSelected: (url: String) -> Unit) {
+ if (!isShowing) return
+ var url by remember { mutableStateOf("") }
+ Dialog(onDismissRequest = {
+ url = ""
+ onDismiss()
+ }) {
+ Surface(
+ shape = RoundedCornerShape(4.dp),
+ ) {
+ Column(
+ modifier = Modifier.padding(16.dp)
+ ) {
+ Text(
+ stringResource(R.string.enter_url),
+ fontSize = 18.sp,
+ )
+ OutlinedTextField(
+ value = url,
+ onValueChange = { url = it },
+ label = { Text(stringResource(R.string.url)) },
+ )
+ TextButton(
+ onClick = { onUrlSelected(url) },
+ modifier = Modifier.align(Alignment.End)
+ ) {
+ Text(stringResource(R.string.ok))
+ }
+ }
+ }
+ }
+}
+
+@Composable
private fun AssetRow(name: String, onClick: () -> Unit) {
Surface(
modifier = Modifier
diff --git a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ui/Color.kt b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ui/Color.kt
index f535838..9dcba77 100644
--- a/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ui/Color.kt
+++ b/sample-compose/src/main/java/com/airbnb/lottie/sample/compose/ui/Color.kt
@@ -10,8 +10,6 @@
val TealDark = Color(0xFF484848)
val Teal = Color(0xFF009587)
-val bottomBarBackground = Color(0xFFF7F7F7)
-
@ColorInt
fun String?.toColorSafe(): Color {
var bgColor = this ?: "#ffffff"
diff --git a/sample-compose/src/main/res/drawable/ic_layers.xml b/sample-compose/src/main/res/drawable/ic_layers.xml
new file mode 100644
index 0000000..5a8a75a
--- /dev/null
+++ b/sample-compose/src/main/res/drawable/ic_layers.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11.99,18.54l-7.37,-5.73L3,14.07l9,7 9,-7 -1.63,-1.27 -7.38,5.74zM12,16l7.36,-5.73L21,9l-9,-7 -9,7 1.63,1.27L12,16z"/>
+</vector>
diff --git a/sample-compose/src/main/res/drawable/ic_masks_and_mattes.xml b/sample-compose/src/main/res/drawable/ic_masks_and_mattes.xml
new file mode 100644
index 0000000..9c219d4
--- /dev/null
+++ b/sample-compose/src/main/res/drawable/ic_masks_and_mattes.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="#FF000000">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
+</vector>
diff --git a/sample-compose/src/main/res/drawable/ic_warning.xml b/sample-compose/src/main/res/drawable/ic_warning.xml
deleted file mode 100644
index be51d26..0000000
--- a/sample-compose/src/main/res/drawable/ic_warning.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="16dp"
- android:height="16dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#ff7e7e7e"
- android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
-</vector>
diff --git a/sample-compose/src/main/res/values/strings.xml b/sample-compose/src/main/res/values/strings.xml
index 00faace..eedfa5b 100644
--- a/sample-compose/src/main/res/values/strings.xml
+++ b/sample-compose/src/main/res/values/strings.xml
@@ -9,9 +9,11 @@
<string name="tab_recent">Recent</string>
<string name="tab_popular">Popular</string>
<string name="tab_search">Search</string>
+ <string name="query">Query</string>
<string name="tab_preview">Preview</string>
<string name="scan_qr_code">Scan a QR code</string>
<string name="open_file">Open a file</string>
+ <string name="url">URL</string>
<string name="enter_url">Enter a URL to a json or zip file</string>
<string name="load_from_assets">Load from assets</string>
@@ -20,8 +22,11 @@
<item quantity="other">%1$d warnings</item>
</plurals>
<string name="toolbar_item_border">Border</string>
+ <string name="toolbar_item_masks">Outline Masks</string>
<string name="toolbar_item_speed">Speed</string>
<string name="toolbar_item_color">Background</string>
+ <string name="toolbar_item_outline_masks">Outline Masks</string>
+ <string name="toolbar_item_opacity_layers">Apply Opacity To Layers</string>
<string name="failed_to_load">Failed to load composition</string>
<string name="ok">OK</string>