1 package com.airbnb.lottie.sample.compose.examples
2
3 import androidx.compose.foundation.background
4 import androidx.compose.foundation.clickable
5 import androidx.compose.foundation.layout.Box
6 import androidx.compose.foundation.layout.Column
7 import androidx.compose.foundation.layout.fillMaxWidth
8 import androidx.compose.foundation.layout.padding
9 import androidx.compose.foundation.layout.size
10 import androidx.compose.foundation.rememberScrollState
11 import androidx.compose.foundation.verticalScroll
12 import androidx.compose.material.Slider
13 import androidx.compose.runtime.Composable
14 import androidx.compose.runtime.LaunchedEffect
15 import androidx.compose.runtime.getValue
16 import androidx.compose.runtime.mutableStateOf
17 import androidx.compose.runtime.remember
18 import androidx.compose.runtime.setValue
19 import androidx.compose.ui.Alignment
20 import androidx.compose.ui.Modifier
21 import androidx.compose.ui.graphics.Color
22 import androidx.compose.ui.unit.dp
23 import com.airbnb.lottie.compose.rememberLottieAnimatable
24 import com.airbnb.lottie.compose.LottieAnimation
25 import com.airbnb.lottie.compose.LottieCompositionSpec
26 import com.airbnb.lottie.compose.LottieConstants
27 import com.airbnb.lottie.compose.rememberLottieComposition
28 import com.airbnb.lottie.sample.compose.R
29
30 @Composable
AnimatableExamplesPagenull31 fun AnimatableExamplesPage() {
32 UsageExamplePageScaffold {
33 Column(
34 modifier = Modifier
35 .fillMaxWidth()
36 .verticalScroll(rememberScrollState())
37 ) {
38 ExampleCard("Example 1", "Repeat Forever") {
39 Example1()
40 }
41 ExampleCard("Example 2", "Draggable Progress Slider") {
42 Example2()
43 }
44 ExampleCard("Example 3", "Draggable Speed Slider") {
45 Example3()
46 }
47 ExampleCard("Example 4", "Repeat once. Click to repeat again") {
48 Example4()
49 }
50 ExampleCard("Example 5", "Click to toggle playback") {
51 Example5()
52 }
53 ExampleCard("Example 6", "Reverse Animation on Repeat") {
54 Example6()
55 }
56 }
57 }
58 }
59
60 @Composable
Example1null61 private fun Example1() {
62 val anim = rememberLottieAnimatable()
63 val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.heart))
64 LaunchedEffect(composition) {
65 anim.animate(
66 composition,
67 iterations = LottieConstants.IterateForever,
68 )
69 }
70 LottieAnimation(anim.composition, { anim.progress })
71 }
72
73 @Composable
Example2null74 private fun Example2() {
75 val anim = rememberLottieAnimatable()
76 val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.heart))
77 var sliderGestureProgress: Float? by remember { mutableStateOf(null) }
78 LaunchedEffect(composition, sliderGestureProgress) {
79 when (val p = sliderGestureProgress) {
80 null -> anim.animate(
81 composition,
82 iterations = LottieConstants.IterateForever,
83 initialProgress = anim.progress,
84 continueFromPreviousAnimate = false,
85 )
86 else -> anim.snapTo(progress = p)
87 }
88 }
89 Box {
90 LottieAnimation(anim.composition, { anim.progress })
91 Slider(
92 value = sliderGestureProgress ?: anim.progress,
93 onValueChange = { sliderGestureProgress = it },
94 onValueChangeFinished = { sliderGestureProgress = null },
95 modifier = Modifier
96 .align(Alignment.BottomCenter)
97 .padding(bottom = 8.dp)
98 )
99 }
100 }
101
102 @Composable
Example3null103 private fun Example3() {
104 val anim = rememberLottieAnimatable()
105 val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.heart))
106 var speed by remember { mutableStateOf(1f) }
107 LaunchedEffect(composition, speed) {
108 anim.animate(
109 composition,
110 iterations = LottieConstants.IterateForever,
111 speed = speed,
112 initialProgress = anim.progress,
113 )
114 }
115 Box {
116 LottieAnimation(composition, { anim.progress })
117 Slider(
118 value = speed,
119 onValueChange = { speed = it },
120 valueRange = -3f..3f,
121 modifier = Modifier
122 .align(Alignment.BottomCenter)
123 .padding(bottom = 8.dp)
124 )
125 Box(
126 modifier = Modifier
127 .align(Alignment.BottomCenter)
128 .padding(bottom = 24.dp)
129 .size(width = 1.dp, height = 16.dp)
130 .background(Color.Black)
131 )
132 }
133 }
134
135 @Composable
Example4null136 private fun Example4() {
137 var nonce by remember { mutableStateOf(1) }
138 val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.heart))
139 val animatable = rememberLottieAnimatable()
140
141 LaunchedEffect(composition, nonce) {
142 composition ?: return@LaunchedEffect
143 animatable.animate(
144 composition,
145 continueFromPreviousAnimate = false,
146 )
147 }
148 LottieAnimation(
149 composition,
150 { animatable.progress },
151 modifier = Modifier
152 .clickable { nonce++ }
153 )
154 }
155
156 @Composable
Example5null157 private fun Example5() {
158 var shouldPlay by remember { mutableStateOf(true) }
159 val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.heart))
160 val animatable = rememberLottieAnimatable()
161
162 LaunchedEffect(composition, shouldPlay) {
163 if (composition == null || !shouldPlay) return@LaunchedEffect
164 animatable.animate(composition, iteration = LottieConstants.IterateForever)
165 }
166 LottieAnimation(
167 composition,
168 { animatable.progress },
169 modifier = Modifier
170 .clickable { shouldPlay = !shouldPlay }
171 )
172 }
173
174 @Composable
Example6null175 private fun Example6() {
176 val anim = rememberLottieAnimatable()
177 val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.heart))
178 LaunchedEffect(composition) {
179 anim.animate(
180 composition,
181 iterations = LottieConstants.IterateForever,
182 reverseOnRepeat = true,
183 )
184 }
185 LottieAnimation(anim.composition, { anim.progress })
186 }
187
188