Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Jetpack Compose for Games & Animations

Jetpack Compose for Games & Animations

NOTE: This slide contains animated GIFs which are not supported SpeakerDeck. You can watch the original animated version at http://slides.com/wajahatkarim/composeanimations

Are you excited about Jetpack Compose? Do you love playing & making games? Have you got that designer itch which makes you want to develop creative apps? Or you love the motion design and micro-interactions?

Although Jetpack Compose is a toolkit to create Android UI in a declarative form with the power of Kotlin language. But it can be used as a canvas for generative art, animations, or even games.

In this session, we'll take a look at the capabilities of Canvas API for Jetpack Compose and how can we implement different kinds of animations with it. We'll also dig into game development and discuss some common challenges like game loop, state management etc. We will also explore other UI animations and transitions with Jetpack Compose.

By the end of this talk, we'll be more familiar with the concepts of Canvas in Jetpack Compose and how we can use it during development to write animations or games.

Wajahat Karim

October 09, 2020
Tweet

More Decks by Wajahat Karim

Other Decks in Education

Transcript

  1. Jetpack Compose for Games & Animations Wajahat Karim wajahatkarim.com WajahatKarim

    Google Dev Expert (GDE) in Android . Android Dev. Open Source Contributor . Technical Writer . Public Speaker 1
  2. Jetpack Compose “ a modern UI toolkit which simplifies and

    accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs. d.android.com/jetpack/compose 2
  3. Animations in Jetpack Compose The animateContentSize() Modifier The AnimatedVisibility Composable

    Single Value Animations with animate() Repeated Animations with AnimatedValue Utilizing transitions to make solid animations 4
  4. Animations in Jetpack Compose The animateContentSize() Modifier The AnimatedVisibility Composable

    Single Value Animations with animate() Repeated Animations with AnimatedValue Utilizing transitions to make solid animations 5
  5. animateContentSize() Modifier @Composable fun ExpandableText() { val shortText = "Click

    me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" var short by remember { mutableStateOf(true) } Box( modifier = Modifier .background( Color.Blue, RoundedCornerShape(15.dp) ) .clickable { short = !short } .padding(20.dp) .wrapContentSize() .animateContentSize() ) { Text( if (short) { shortText } else { longText }, style = TextStyle(color = Color.White) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 6
  6. animateContentSize() Modifier @Composable fun ExpandableText() { val shortText = "Click

    me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" var short by remember { mutableStateOf(true) } Box( modifier = Modifier .background( Color.Blue, RoundedCornerShape(15.dp) ) .clickable { short = !short } .padding(20.dp) .wrapContentSize() .animateContentSize() ) { Text( if (short) { shortText } else { longText }, style = TextStyle(color = Color.White) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 val shortText = "Click me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" @Composable 1 fun ExpandableText() { 2 3 4 5 6 var short by remember { mutableStateOf(true) } 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 .clickable { short = !short } 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 if (short) { 20 shortText 21 } else { 22 longText 23 }, 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 6
  7. animateContentSize() Modifier @Composable fun ExpandableText() { val shortText = "Click

    me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" var short by remember { mutableStateOf(true) } Box( modifier = Modifier .background( Color.Blue, RoundedCornerShape(15.dp) ) .clickable { short = !short } .padding(20.dp) .wrapContentSize() .animateContentSize() ) { Text( if (short) { shortText } else { longText }, style = TextStyle(color = Color.White) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 val shortText = "Click me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" @Composable 1 fun ExpandableText() { 2 3 4 5 6 var short by remember { mutableStateOf(true) } 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 .clickable { short = !short } 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 if (short) { 20 shortText 21 } else { 22 longText 23 }, 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 var short by remember { mutableStateOf(true) } .clickable { short = !short } if (short) { shortText } else { longText }, @Composable 1 fun ExpandableText() { 2 val shortText = "Click me" 3 val longText = "Very long text passage that spans 4 \nacross multiple lines, paragraphs 5 \nand pages" 6 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 20 21 22 23 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 6
  8. animateContentSize() Modifier @Composable fun ExpandableText() { val shortText = "Click

    me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" var short by remember { mutableStateOf(true) } Box( modifier = Modifier .background( Color.Blue, RoundedCornerShape(15.dp) ) .clickable { short = !short } .padding(20.dp) .wrapContentSize() .animateContentSize() ) { Text( if (short) { shortText } else { longText }, style = TextStyle(color = Color.White) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 val shortText = "Click me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" @Composable 1 fun ExpandableText() { 2 3 4 5 6 var short by remember { mutableStateOf(true) } 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 .clickable { short = !short } 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 if (short) { 20 shortText 21 } else { 22 longText 23 }, 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 var short by remember { mutableStateOf(true) } .clickable { short = !short } if (short) { shortText } else { longText }, @Composable 1 fun ExpandableText() { 2 val shortText = "Click me" 3 val longText = "Very long text passage that spans 4 \nacross multiple lines, paragraphs 5 \nand pages" 6 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 20 21 22 23 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 .animateContentSize() @Composable 1 fun ExpandableText() { 2 val shortText = "Click me" 3 val longText = "Very long text passage that spans 4 \nacross multiple lines, paragraphs 5 \nand pages" 6 var short by remember { mutableStateOf(true) } 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 .clickable { short = !short } 14 .padding(20.dp) 15 .wrapContentSize() 16 17 ) { 18 Text( 19 if (short) { 20 shortText 21 } else { 22 longText 23 }, 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 6
  9. animateContentSize() Modifier @Composable fun ExpandableText() { val shortText = "Click

    me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" var short by remember { mutableStateOf(true) } Box( modifier = Modifier .background( Color.Blue, RoundedCornerShape(15.dp) ) .clickable { short = !short } .padding(20.dp) .wrapContentSize() .animateContentSize() ) { Text( if (short) { shortText } else { longText }, style = TextStyle(color = Color.White) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 val shortText = "Click me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" @Composable 1 fun ExpandableText() { 2 3 4 5 6 var short by remember { mutableStateOf(true) } 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 .clickable { short = !short } 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 if (short) { 20 shortText 21 } else { 22 longText 23 }, 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 var short by remember { mutableStateOf(true) } .clickable { short = !short } if (short) { shortText } else { longText }, @Composable 1 fun ExpandableText() { 2 val shortText = "Click me" 3 val longText = "Very long text passage that spans 4 \nacross multiple lines, paragraphs 5 \nand pages" 6 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 14 .padding(20.dp) 15 .wrapContentSize() 16 .animateContentSize() 17 ) { 18 Text( 19 20 21 22 23 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 .animateContentSize() @Composable 1 fun ExpandableText() { 2 val shortText = "Click me" 3 val longText = "Very long text passage that spans 4 \nacross multiple lines, paragraphs 5 \nand pages" 6 var short by remember { mutableStateOf(true) } 7 Box( 8 modifier = Modifier 9 .background( 10 Color.Blue, 11 RoundedCornerShape(15.dp) 12 ) 13 .clickable { short = !short } 14 .padding(20.dp) 15 .wrapContentSize() 16 17 ) { 18 Text( 19 if (short) { 20 shortText 21 } else { 22 longText 23 }, 24 style = TextStyle(color = Color.White) 25 ) 26 } 27 } 28 @Composable fun ExpandableText() { val shortText = "Click me" val longText = "Very long text passage that spans \nacross multiple lines, paragraphs \nand pages" var short by remember { mutableStateOf(true) } Box( modifier = Modifier .background( Color.Blue, RoundedCornerShape(15.dp) ) .clickable { short = !short } .padding(20.dp) .wrapContentSize() .animateContentSize() ) { Text( if (short) { shortText } else { longText }, style = TextStyle(color = Color.White) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 6
  10. animateContentSize() Modifier @Composable fun PortraitModeImage() { var portraitMode by remember

    { mutableStateOf(true) } Box( Modifier.clickable { portraitMode = !portraitMode } .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) .background( if (portraitMode) Color(0xFFfffbd0) else Color( .animateContentSize( animSpec = tween(500, easing = LinearEasing), endListener = { startSize, endSize -> Log.d("droidcon", "$startSize -> $endSize") } ) .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) ) { Text( if (portraitMode) { "3 : 4" } else { "16 : 9" }, style = TextStyle(color = Color.Black) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 7
  11. animateContentSize() Modifier @Composable fun PortraitModeImage() { var portraitMode by remember

    { mutableStateOf(true) } Box( Modifier.clickable { portraitMode = !portraitMode } .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) .background( if (portraitMode) Color(0xFFfffbd0) else Color( .animateContentSize( animSpec = tween(500, easing = LinearEasing), endListener = { startSize, endSize -> Log.d("droidcon", "$startSize -> $endSize") } ) .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) ) { Text( if (portraitMode) { "3 : 4" } else { "16 : 9" }, style = TextStyle(color = Color.Black) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 .animateContentSize( ) @Composable 1 fun PortraitModeImage() { 2 var portraitMode by remember { mutableStateOf(true) } 3 Box( 4 Modifier.clickable { portraitMode = !portraitMode } 5 .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) 6 .background( 7 if (portraitMode) Color(0xFFfffbd0) else Color( 8 9 animSpec = tween(500, easing = LinearEasing), 10 endListener = { startSize, endSize -> 11 Log.d("droidcon", "$startSize -> $endSize") 12 } 13 14 .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) 15 ) { 16 Text( 17 if (portraitMode) { 18 "3 : 4" 19 } else { 20 "16 : 9" 21 }, 22 style = TextStyle(color = Color.Black) 23 ) 24 } 25 } 26 7
  12. animateContentSize() Modifier @Composable fun PortraitModeImage() { var portraitMode by remember

    { mutableStateOf(true) } Box( Modifier.clickable { portraitMode = !portraitMode } .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) .background( if (portraitMode) Color(0xFFfffbd0) else Color( .animateContentSize( animSpec = tween(500, easing = LinearEasing), endListener = { startSize, endSize -> Log.d("droidcon", "$startSize -> $endSize") } ) .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) ) { Text( if (portraitMode) { "3 : 4" } else { "16 : 9" }, style = TextStyle(color = Color.Black) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 .animateContentSize( ) @Composable 1 fun PortraitModeImage() { 2 var portraitMode by remember { mutableStateOf(true) } 3 Box( 4 Modifier.clickable { portraitMode = !portraitMode } 5 .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) 6 .background( 7 if (portraitMode) Color(0xFFfffbd0) else Color( 8 9 animSpec = tween(500, easing = LinearEasing), 10 endListener = { startSize, endSize -> 11 Log.d("droidcon", "$startSize -> $endSize") 12 } 13 14 .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) 15 ) { 16 Text( 17 if (portraitMode) { 18 "3 : 4" 19 } else { 20 "16 : 9" 21 }, 22 style = TextStyle(color = Color.Black) 23 ) 24 } 25 } 26 animSpec = tween(500, easing = LinearEasing), @Composable 1 fun PortraitModeImage() { 2 var portraitMode by remember { mutableStateOf(true) } 3 Box( 4 Modifier.clickable { portraitMode = !portraitMode } 5 .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) 6 .background( 7 if (portraitMode) Color(0xFFfffbd0) else Color( 8 .animateContentSize( 9 10 endListener = { startSize, endSize -> 11 Log.d("droidcon", "$startSize -> $endSize") 12 } 13 ) 14 .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) 15 ) { 16 Text( 17 if (portraitMode) { 18 "3 : 4" 19 } else { 20 "16 : 9" 21 }, 22 style = TextStyle(color = Color.Black) 23 ) 24 } 25 } 26 7
  13. animateContentSize() Modifier @Composable fun PortraitModeImage() { var portraitMode by remember

    { mutableStateOf(true) } Box( Modifier.clickable { portraitMode = !portraitMode } .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) .background( if (portraitMode) Color(0xFFfffbd0) else Color( .animateContentSize( animSpec = tween(500, easing = LinearEasing), endListener = { startSize, endSize -> Log.d("droidcon", "$startSize -> $endSize") } ) .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) ) { Text( if (portraitMode) { "3 : 4" } else { "16 : 9" }, style = TextStyle(color = Color.Black) ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 .animateContentSize( ) @Composable 1 fun PortraitModeImage() { 2 var portraitMode by remember { mutableStateOf(true) } 3 Box( 4 Modifier.clickable { portraitMode = !portraitMode } 5 .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) 6 .background( 7 if (portraitMode) Color(0xFFfffbd0) else Color( 8 9 animSpec = tween(500, easing = LinearEasing), 10 endListener = { startSize, endSize -> 11 Log.d("droidcon", "$startSize -> $endSize") 12 } 13 14 .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) 15 ) { 16 Text( 17 if (portraitMode) { 18 "3 : 4" 19 } else { 20 "16 : 9" 21 }, 22 style = TextStyle(color = Color.Black) 23 ) 24 } 25 } 26 animSpec = tween(500, easing = LinearEasing), @Composable 1 fun PortraitModeImage() { 2 var portraitMode by remember { mutableStateOf(true) } 3 Box( 4 Modifier.clickable { portraitMode = !portraitMode } 5 .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) 6 .background( 7 if (portraitMode) Color(0xFFfffbd0) else Color( 8 .animateContentSize( 9 10 endListener = { startSize, endSize -> 11 Log.d("droidcon", "$startSize -> $endSize") 12 } 13 ) 14 .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) 15 ) { 16 Text( 17 if (portraitMode) { 18 "3 : 4" 19 } else { 20 "16 : 9" 21 }, 22 style = TextStyle(color = Color.Black) 23 ) 24 } 25 } 26 endListener = { startSize, endSize -> Log.d("droidcon", "$startSize -> $endSize") } @Composable 1 fun PortraitModeImage() { 2 var portraitMode by remember { mutableStateOf(true) } 3 Box( 4 Modifier.clickable { portraitMode = !portraitMode } 5 .sizeIn(maxWidth = 300.dp, maxHeight = 300.dp) 6 .background( 7 if (portraitMode) Color(0xFFfffbd0) else Color( 8 .animateContentSize( 9 animSpec = tween(500, easing = LinearEasing), 10 11 12 13 ) 14 .aspectRatio(if (portraitMode) 3 / 4f else 16 / 9f) 15 ) { 16 Text( 17 if (portraitMode) { 18 "3 : 4" 19 } else { 20 "16 : 9" 21 }, 22 style = TextStyle(color = Color.Black) 23 ) 24 } 25 } 26 7
  14. Animations in Jetpack Compose The AnimatedVisibility Composable The animateContentSize() Modifier

    Single Value Animations with animate() Repeated Animations with AnimatedValue Utilizing transitions to make solid animations 8
  15. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically) ) { Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 9
  16. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically) ) { Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 9
  17. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically) ) { Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 5 6 7 8 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 17 } 18 19 20 } 21 9
  18. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically) ) { Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 5 6 7 8 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 17 } 18 19 20 } 21 AnimatedVisibility( @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 9
  19. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically) ) { Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( Text(modifier = Modifier.padding(start = 8.dp), text = "Like") } } @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 5 6 7 8 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 17 } 18 19 20 } 21 AnimatedVisibility( @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 var expanded by remember { mutableStateOf(true) } onClick = { expanded = !expanded }, expanded, @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 4 FloatingActionButton( 5 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 14 modifier = Modifier.align(Alignment.CenterVertically) 15 ) { 16 Text(modifier = Modifier.padding(start = 8.dp), text = "Like") 17 } 18 } 19 } 20 } 21 9
  20. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically), enter = slideInHorizontally( initialOffsetX = { 300 }, animSpec = tween(durationMillis = 2000) ), exit = slideOutVertically( targetOffsetY = { 100 }, animSpec = tween(durationMillis = 2000) ) ) { Text(text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 Default Enter Enter + Exit 10
  21. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically), enter = slideInHorizontally( initialOffsetX = { 300 }, animSpec = tween(durationMillis = 2000) ), exit = slideOutVertically( targetOffsetY = { 100 }, animSpec = tween(durationMillis = 2000) ) ) { Text(text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 enter = slideInHorizontally( initialOffsetX = { 300 }, animSpec = tween(durationMillis = 2000) ), @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically), 15 16 17 18 19 exit = slideOutVertically( 20 targetOffsetY = { 100 }, 21 animSpec = tween(durationMillis = 2000) 22 ) 23 ) { 24 Text(text = "Like") 25 } 26 } 27 } 28 } 29 Default Enter Enter + Exit 10
  22. AnimatedVisbility Composable @OptIn(ExperimentalAnimationApi::class) @Composable fun VisibilityAnimationFAB() { var expanded by

    remember { mutableStateOf(true) } FloatingActionButton( onClick = { expanded = !expanded }, ) { Row(Modifier.padding(start = 16.dp, end = 16.dp)) { Icon( asset = Icons.Default.Favorite, Modifier.align(Alignment.CenterVertically) ) AnimatedVisibility( expanded, modifier = Modifier.align(Alignment.CenterVertically), enter = slideInHorizontally( initialOffsetX = { 300 }, animSpec = tween(durationMillis = 2000) ), exit = slideOutVertically( targetOffsetY = { 100 }, animSpec = tween(durationMillis = 2000) ) ) { Text(text = "Like") } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 enter = slideInHorizontally( initialOffsetX = { 300 }, animSpec = tween(durationMillis = 2000) ), @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically), 15 16 17 18 19 exit = slideOutVertically( 20 targetOffsetY = { 100 }, 21 animSpec = tween(durationMillis = 2000) 22 ) 23 ) { 24 Text(text = "Like") 25 } 26 } 27 } 28 } 29 exit = slideOutVertically( targetOffsetY = { 100 }, animSpec = tween(durationMillis = 2000) ) @OptIn(ExperimentalAnimationApi::class) 1 @Composable 2 fun VisibilityAnimationFAB() { 3 var expanded by remember { mutableStateOf(true) } 4 FloatingActionButton( 5 onClick = { expanded = !expanded }, 6 ) { 7 Row(Modifier.padding(start = 16.dp, end = 16.dp)) { 8 Icon( 9 asset = Icons.Default.Favorite, 10 Modifier.align(Alignment.CenterVertically) 11 ) 12 AnimatedVisibility( 13 expanded, 14 modifier = Modifier.align(Alignment.CenterVertically), 15 enter = slideInHorizontally( 16 initialOffsetX = { 300 }, 17 animSpec = tween(durationMillis = 2000) 18 ), 19 20 21 22 23 ) { 24 Text(text = "Like") 25 } 26 } 27 } 28 } 29 Default Enter Enter + Exit 10
  23. Animations in Jetpack Compose Single Value Animations with animate() The

    animateContentSize() Modifier The AnimatedVisibility Composable Single Value Animations with animate() Repeated Animations with AnimatedValue Utilizing transitions to make solid animations 12
  24. @Composable fun ScaleAndColorAnimation() { val enabled = remember { mutableStateOf(true)

    } val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp Button( onClick = { enabled.value = !enabled.value }, backgroundColor = animate(color), modifier = Modifier .padding(16.dp) .preferredHeight(animate(height)) .preferredWidth(animate(width)), ) { Text("Scale & Color") } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 The animate() A simple method for animations between current and target state. Supports Int, Dp, Color, Rect and many more types. 13
  25. @Composable fun ScaleAndColorAnimation() { val enabled = remember { mutableStateOf(true)

    } val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp Button( onClick = { enabled.value = !enabled.value }, backgroundColor = animate(color), modifier = Modifier .padding(16.dp) .preferredHeight(animate(height)) .preferredWidth(animate(width)), ) { Text("Scale & Color") } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp @Composable 1 fun ScaleAndColorAnimation() { 2 val enabled = remember { mutableStateOf(true) } 3 4 5 6 7 8 9 Button( 10 onClick = { enabled.value = !enabled.value }, 11 backgroundColor = animate(color), 12 modifier = Modifier 13 .padding(16.dp) 14 .preferredHeight(animate(height)) 15 .preferredWidth(animate(width)), 16 ) { 17 Text("Scale & Color") 18 } 19 } 20 The animate() A simple method for animations between current and target state. Supports Int, Dp, Color, Rect and many more types. 13
  26. @Composable fun ScaleAndColorAnimation() { val enabled = remember { mutableStateOf(true)

    } val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp Button( onClick = { enabled.value = !enabled.value }, backgroundColor = animate(color), modifier = Modifier .padding(16.dp) .preferredHeight(animate(height)) .preferredWidth(animate(width)), ) { Text("Scale & Color") } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp @Composable 1 fun ScaleAndColorAnimation() { 2 val enabled = remember { mutableStateOf(true) } 3 4 5 6 7 8 9 Button( 10 onClick = { enabled.value = !enabled.value }, 11 backgroundColor = animate(color), 12 modifier = Modifier 13 .padding(16.dp) 14 .preferredHeight(animate(height)) 15 .preferredWidth(animate(width)), 16 ) { 17 Text("Scale & Color") 18 } 19 } 20 backgroundColor = animate(color), @Composable 1 fun ScaleAndColorAnimation() { 2 val enabled = remember { mutableStateOf(true) } 3 val color = if (enabled.value) MaterialTheme.colors.primary 4 else MaterialTheme.colors.secondary 5 6 val height = if (enabled.value) 40.dp else 60.dp 7 val width = if (enabled.value) 150.dp else 300.dp 8 9 Button( 10 onClick = { enabled.value = !enabled.value }, 11 12 modifier = Modifier 13 .padding(16.dp) 14 .preferredHeight(animate(height)) 15 .preferredWidth(animate(width)), 16 ) { 17 Text("Scale & Color") 18 } 19 } 20 The animate() A simple method for animations between current and target state. Supports Int, Dp, Color, Rect and many more types. 13
  27. @Composable fun ScaleAndColorAnimation() { val enabled = remember { mutableStateOf(true)

    } val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp Button( onClick = { enabled.value = !enabled.value }, backgroundColor = animate(color), modifier = Modifier .padding(16.dp) .preferredHeight(animate(height)) .preferredWidth(animate(width)), ) { Text("Scale & Color") } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val color = if (enabled.value) MaterialTheme.colors.primary else MaterialTheme.colors.secondary val height = if (enabled.value) 40.dp else 60.dp val width = if (enabled.value) 150.dp else 300.dp @Composable 1 fun ScaleAndColorAnimation() { 2 val enabled = remember { mutableStateOf(true) } 3 4 5 6 7 8 9 Button( 10 onClick = { enabled.value = !enabled.value }, 11 backgroundColor = animate(color), 12 modifier = Modifier 13 .padding(16.dp) 14 .preferredHeight(animate(height)) 15 .preferredWidth(animate(width)), 16 ) { 17 Text("Scale & Color") 18 } 19 } 20 backgroundColor = animate(color), @Composable 1 fun ScaleAndColorAnimation() { 2 val enabled = remember { mutableStateOf(true) } 3 val color = if (enabled.value) MaterialTheme.colors.primary 4 else MaterialTheme.colors.secondary 5 6 val height = if (enabled.value) 40.dp else 60.dp 7 val width = if (enabled.value) 150.dp else 300.dp 8 9 Button( 10 onClick = { enabled.value = !enabled.value }, 11 12 modifier = Modifier 13 .padding(16.dp) 14 .preferredHeight(animate(height)) 15 .preferredWidth(animate(width)), 16 ) { 17 Text("Scale & Color") 18 } 19 } 20 .preferredHeight(animate(height)) .preferredWidth(animate(width)), @Composable 1 fun ScaleAndColorAnimation() { 2 val enabled = remember { mutableStateOf(true) } 3 val color = if (enabled.value) MaterialTheme.colors.primary 4 else MaterialTheme.colors.secondary 5 6 val height = if (enabled.value) 40.dp else 60.dp 7 val width = if (enabled.value) 150.dp else 300.dp 8 9 Button( 10 onClick = { enabled.value = !enabled.value }, 11 backgroundColor = animate(color), 12 modifier = Modifier 13 .padding(16.dp) 14 15 16 ) { 17 Text("Scale & Color") 18 } 19 } 20 The animate() A simple method for animations between current and target state. Supports Int, Dp, Color, Rect and many more types. 13
  28. @Composable fun GenderSelectAnimation() { val female = remember { mutableStateOf(true)

    } Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Image( asset = imageResource(R.drawable.male), contentScale = ContentScale.Crop, modifier = Modifier .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .padding(8.dp) .clickable { female.value = !female.value } .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) ) Image( asset = imageResource(R.drawable.female), contentScale = ContentScale.Crop, modifier = Modifier // ... // Like previous image ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 The animate() 14
  29. @Composable fun GenderSelectAnimation() { val female = remember { mutableStateOf(true)

    } Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Image( asset = imageResource(R.drawable.male), contentScale = ContentScale.Crop, modifier = Modifier .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .padding(8.dp) .clickable { female.value = !female.value } .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) ) Image( asset = imageResource(R.drawable.female), contentScale = ContentScale.Crop, modifier = Modifier // ... // Like previous image ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 val female = remember { mutableStateOf(true) } .clickable { female.value = !female.value } @Composable 1 fun GenderSelectAnimation() { 2 3 Row(horizontalArrangement = Arrangement.Center, 4 modifier = Modifier.padding(8.dp).fillMaxWidth(), 5 verticalAlignment = Alignment.CenterVertically 6 ) { 7 Image( 8 asset = imageResource(R.drawable.male), 9 contentScale = ContentScale.Crop, 10 modifier = Modifier 11 .preferredSize(animate(if (female.value) 100.dp else 250.dp)) 12 .border(width = animate(if (female.value) 0.dp else 4.dp), 13 color = animate(if (female.value) Color.Transparent else Color.Red)) 14 .padding(8.dp) 15 16 .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) 17 ) 18 Image( 19 asset = imageResource(R.drawable.female), 20 contentScale = ContentScale.Crop, 21 modifier = Modifier 22 // ... 23 // Like previous image 24 ) 25 } 26 } 27 The animate() 14
  30. @Composable fun GenderSelectAnimation() { val female = remember { mutableStateOf(true)

    } Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Image( asset = imageResource(R.drawable.male), contentScale = ContentScale.Crop, modifier = Modifier .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .padding(8.dp) .clickable { female.value = !female.value } .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) ) Image( asset = imageResource(R.drawable.female), contentScale = ContentScale.Crop, modifier = Modifier // ... // Like previous image ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 val female = remember { mutableStateOf(true) } .clickable { female.value = !female.value } @Composable 1 fun GenderSelectAnimation() { 2 3 Row(horizontalArrangement = Arrangement.Center, 4 modifier = Modifier.padding(8.dp).fillMaxWidth(), 5 verticalAlignment = Alignment.CenterVertically 6 ) { 7 Image( 8 asset = imageResource(R.drawable.male), 9 contentScale = ContentScale.Crop, 10 modifier = Modifier 11 .preferredSize(animate(if (female.value) 100.dp else 250.dp)) 12 .border(width = animate(if (female.value) 0.dp else 4.dp), 13 color = animate(if (female.value) Color.Transparent else Color.Red)) 14 .padding(8.dp) 15 16 .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) 17 ) 18 Image( 19 asset = imageResource(R.drawable.female), 20 contentScale = ContentScale.Crop, 21 modifier = Modifier 22 // ... 23 // Like previous image 24 ) 25 } 26 } 27 .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) @Composable 1 fun GenderSelectAnimation() { 2 val female = remember { mutableStateOf(true) } 3 Row(horizontalArrangement = Arrangement.Center, 4 modifier = Modifier.padding(8.dp).fillMaxWidth(), 5 verticalAlignment = Alignment.CenterVertically 6 ) { 7 Image( 8 asset = imageResource(R.drawable.male), 9 contentScale = ContentScale.Crop, 10 modifier = Modifier 11 12 13 14 .padding(8.dp) 15 .clickable { female.value = !female.value } 16 17 ) 18 Image( 19 asset = imageResource(R.drawable.female), 20 contentScale = ContentScale.Crop, 21 modifier = Modifier 22 // ... 23 // Like previous image 24 ) 25 } 26 } 27 The animate() 14
  31. @Composable fun GenderSelectAnimation() { val female = remember { mutableStateOf(true)

    } Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Image( asset = imageResource(R.drawable.male), contentScale = ContentScale.Crop, modifier = Modifier .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .padding(8.dp) .clickable { female.value = !female.value } .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) ) Image( asset = imageResource(R.drawable.female), contentScale = ContentScale.Crop, modifier = Modifier // ... // Like previous image ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 val female = remember { mutableStateOf(true) } .clickable { female.value = !female.value } @Composable 1 fun GenderSelectAnimation() { 2 3 Row(horizontalArrangement = Arrangement.Center, 4 modifier = Modifier.padding(8.dp).fillMaxWidth(), 5 verticalAlignment = Alignment.CenterVertically 6 ) { 7 Image( 8 asset = imageResource(R.drawable.male), 9 contentScale = ContentScale.Crop, 10 modifier = Modifier 11 .preferredSize(animate(if (female.value) 100.dp else 250.dp)) 12 .border(width = animate(if (female.value) 0.dp else 4.dp), 13 color = animate(if (female.value) Color.Transparent else Color.Red)) 14 .padding(8.dp) 15 16 .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) 17 ) 18 Image( 19 asset = imageResource(R.drawable.female), 20 contentScale = ContentScale.Crop, 21 modifier = Modifier 22 // ... 23 // Like previous image 24 ) 25 } 26 } 27 .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) @Composable 1 fun GenderSelectAnimation() { 2 val female = remember { mutableStateOf(true) } 3 Row(horizontalArrangement = Arrangement.Center, 4 modifier = Modifier.padding(8.dp).fillMaxWidth(), 5 verticalAlignment = Alignment.CenterVertically 6 ) { 7 Image( 8 asset = imageResource(R.drawable.male), 9 contentScale = ContentScale.Crop, 10 modifier = Modifier 11 12 13 14 .padding(8.dp) 15 .clickable { female.value = !female.value } 16 17 ) 18 Image( 19 asset = imageResource(R.drawable.female), 20 contentScale = ContentScale.Crop, 21 modifier = Modifier 22 // ... 23 // Like previous image 24 ) 25 } 26 } 27 @Composable fun GenderSelectAnimation() { val female = remember { mutableStateOf(true) } Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Image( asset = imageResource(R.drawable.male), contentScale = ContentScale.Crop, modifier = Modifier .preferredSize(animate(if (female.value) 100.dp else 250.dp)) .border(width = animate(if (female.value) 0.dp else 4.dp), color = animate(if (female.value) Color.Transparent else Color.Red)) .padding(8.dp) .clickable { female.value = !female.value } .clip(RoundedCornerShape(animate(if (female.value) 0.dp else 8.dp))) ) Image( asset = imageResource(R.drawable.female), contentScale = ContentScale.Crop, modifier = Modifier // ... // Like previous image ) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 The animate() 14
  32. Animations in Jetpack Compose Repeated Animations with AnimatedValue The animateContentSize()

    Modifier The AnimatedVisibility Composable Single Value Animations with animate() Repeated Animations with AnimatedValue Utilizing transitions to make solid animations 16
  33. @Composable fun HeartBeatDemo() { val animScale = animatedFloat(initVal = 1f)

    val animColor = animatedColor(initVal = Color.Red) onActive { animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) animColor.animateTo( targetValue = Color.Blue, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = LinearEasing, delayMillis = 1000) ) ) } Image(asset = Icons.Default.Favorite, modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Repeated Animations with AnimatedValue 17
  34. @Composable fun HeartBeatDemo() { val animScale = animatedFloat(initVal = 1f)

    val animColor = animatedColor(initVal = Color.Red) onActive { animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) animColor.animateTo( targetValue = Color.Blue, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = LinearEasing, delayMillis = 1000) ) ) } Image(asset = Icons.Default.Favorite, modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 val animScale = animatedFloat(initVal = 1f) val animColor = animatedColor(initVal = Color.Red) @Composable 1 fun HeartBeatDemo() { 2 3 4 5 onActive { 6 animScale.animateTo( 7 targetValue = 1.3f, 8 anim = repeatable( 9 iterations = AnimationConstants.Infinite, 10 animation = tween(durationMillis = 300, 11 easing = FastOutLinearInEasing, delayMillis = 1000) 12 ) 13 ) 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 Repeated Animations with AnimatedValue 17
  35. @Composable fun HeartBeatDemo() { val animScale = animatedFloat(initVal = 1f)

    val animColor = animatedColor(initVal = Color.Red) onActive { animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) animColor.animateTo( targetValue = Color.Blue, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = LinearEasing, delayMillis = 1000) ) ) } Image(asset = Icons.Default.Favorite, modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 val animScale = animatedFloat(initVal = 1f) val animColor = animatedColor(initVal = Color.Red) @Composable 1 fun HeartBeatDemo() { 2 3 4 5 onActive { 6 animScale.animateTo( 7 targetValue = 1.3f, 8 anim = repeatable( 9 iterations = AnimationConstants.Infinite, 10 animation = tween(durationMillis = 300, 11 easing = FastOutLinearInEasing, delayMillis = 1000) 12 ) 13 ) 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) @Composable 1 fun HeartBeatDemo() { 2 val animScale = animatedFloat(initVal = 1f) 3 val animColor = animatedColor(initVal = Color.Red) 4 5 onActive { 6 7 8 9 10 11 12 13 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 Repeated Animations with AnimatedValue 17
  36. @Composable fun HeartBeatDemo() { val animScale = animatedFloat(initVal = 1f)

    val animColor = animatedColor(initVal = Color.Red) onActive { animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) animColor.animateTo( targetValue = Color.Blue, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = LinearEasing, delayMillis = 1000) ) ) } Image(asset = Icons.Default.Favorite, modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 val animScale = animatedFloat(initVal = 1f) val animColor = animatedColor(initVal = Color.Red) @Composable 1 fun HeartBeatDemo() { 2 3 4 5 onActive { 6 animScale.animateTo( 7 targetValue = 1.3f, 8 anim = repeatable( 9 iterations = AnimationConstants.Infinite, 10 animation = tween(durationMillis = 300, 11 easing = FastOutLinearInEasing, delayMillis = 1000) 12 ) 13 ) 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) @Composable 1 fun HeartBeatDemo() { 2 val animScale = animatedFloat(initVal = 1f) 3 val animColor = animatedColor(initVal = Color.Red) 4 5 onActive { 6 7 8 9 10 11 12 13 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) @Composable 1 fun HeartBeatDemo() { 2 val animScale = animatedFloat(initVal = 1f) 3 val animColor = animatedColor(initVal = Color.Red) 4 5 onActive { 6 animScale.animateTo( 7 targetValue = 1.3f, 8 anim = repeatable( 9 iterations = AnimationConstants.Infinite, 10 animation = tween(durationMillis = 300, 11 easing = FastOutLinearInEasing, delayMillis = 1000) 12 ) 13 ) 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 27 28 ) 29 } 30 Repeated Animations with AnimatedValue 17
  37. @Composable fun HeartBeatDemo() { val animScale = animatedFloat(initVal = 1f)

    val animColor = animatedColor(initVal = Color.Red) onActive { animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) animColor.animateTo( targetValue = Color.Blue, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = LinearEasing, delayMillis = 1000) ) ) } Image(asset = Icons.Default.Favorite, modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 val animScale = animatedFloat(initVal = 1f) val animColor = animatedColor(initVal = Color.Red) @Composable 1 fun HeartBeatDemo() { 2 3 4 5 onActive { 6 animScale.animateTo( 7 targetValue = 1.3f, 8 anim = repeatable( 9 iterations = AnimationConstants.Infinite, 10 animation = tween(durationMillis = 300, 11 easing = FastOutLinearInEasing, delayMillis = 1000) 12 ) 13 ) 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) @Composable 1 fun HeartBeatDemo() { 2 val animScale = animatedFloat(initVal = 1f) 3 val animColor = animatedColor(initVal = Color.Red) 4 5 onActive { 6 7 8 9 10 11 12 13 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), 27 colorFilter = ColorFilter.tint(animColor.value) 28 ) 29 } 30 modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) @Composable 1 fun HeartBeatDemo() { 2 val animScale = animatedFloat(initVal = 1f) 3 val animColor = animatedColor(initVal = Color.Red) 4 5 onActive { 6 animScale.animateTo( 7 targetValue = 1.3f, 8 anim = repeatable( 9 iterations = AnimationConstants.Infinite, 10 animation = tween(durationMillis = 300, 11 easing = FastOutLinearInEasing, delayMillis = 1000) 12 ) 13 ) 14 15 animColor.animateTo( 16 targetValue = Color.Blue, 17 anim = repeatable( 18 iterations = AnimationConstants.Infinite, 19 animation = tween(durationMillis = 300, 20 easing = LinearEasing, delayMillis = 1000) 21 ) 22 ) 23 } 24 25 Image(asset = Icons.Default.Favorite, 26 27 28 ) 29 } 30 @Composable fun HeartBeatDemo() { val animScale = animatedFloat(initVal = 1f) val animColor = animatedColor(initVal = Color.Red) onActive { animScale.animateTo( targetValue = 1.3f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = FastOutLinearInEasing, delayMillis = 1000) ) ) animColor.animateTo( targetValue = Color.Blue, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 300, easing = LinearEasing, delayMillis = 1000) ) ) } Image(asset = Icons.Default.Favorite, modifier = Modifier.padding(10.dp).size((40*animScale.value).dp), colorFilter = ColorFilter.tint(animColor.value) ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Repeated Animations with AnimatedValue 17
  38. Compose Canvas 101 A simple Spacer() to allow you to

    draw anything on it @Composable fun Canvas ( modifier: Modifier, onDraw: DrawScope.() -> Unit ) = Spacer(modifier.drawBehind(onDraw)) 1 2 3 4 5 6 18
  39. Compose Canvas 101 A simple Spacer() to allow you to

    draw anything on it @Composable fun Canvas ( modifier: Modifier, onDraw: DrawScope.() -> Unit ) = Spacer(modifier.drawBehind(onDraw)) 1 2 3 4 5 6 ) = Spacer(modifier.drawBehind(onDraw)) @Composable 1 fun Canvas 2 ( 3 modifier: Modifier, 4 onDraw: DrawScope.() -> Unit 5 6 18
  40. Compose Canvas 101 A simple Spacer() to allow you to

    draw anything on it @Composable fun Canvas ( modifier: Modifier, onDraw: DrawScope.() -> Unit ) = Spacer(modifier.drawBehind(onDraw)) 1 2 3 4 5 6 ) = Spacer(modifier.drawBehind(onDraw)) @Composable 1 fun Canvas 2 ( 3 modifier: Modifier, 4 onDraw: DrawScope.() -> Unit 5 6 modifier: Modifier, @Composable 1 fun Canvas 2 ( 3 4 onDraw: DrawScope.() -> Unit 5 ) = Spacer(modifier.drawBehind(onDraw)) 6 18
  41. Compose Canvas 101 A simple Spacer() to allow you to

    draw anything on it @Composable fun Canvas ( modifier: Modifier, onDraw: DrawScope.() -> Unit ) = Spacer(modifier.drawBehind(onDraw)) 1 2 3 4 5 6 ) = Spacer(modifier.drawBehind(onDraw)) @Composable 1 fun Canvas 2 ( 3 modifier: Modifier, 4 onDraw: DrawScope.() -> Unit 5 6 modifier: Modifier, @Composable 1 fun Canvas 2 ( 3 4 onDraw: DrawScope.() -> Unit 5 ) = Spacer(modifier.drawBehind(onDraw)) 6 onDraw: DrawScope.() -> Unit @Composable 1 fun Canvas 2 ( 3 modifier: Modifier, 4 5 ) = Spacer(modifier.drawBehind(onDraw)) 6 18
  42. Compose Canvas 101 A simple Spacer() to allow you to

    draw anything on it @Composable fun Canvas ( modifier: Modifier, onDraw: DrawScope.() -> Unit ) = Spacer(modifier.drawBehind(onDraw)) 1 2 3 4 5 6 ) = Spacer(modifier.drawBehind(onDraw)) @Composable 1 fun Canvas 2 ( 3 modifier: Modifier, 4 onDraw: DrawScope.() -> Unit 5 6 modifier: Modifier, @Composable 1 fun Canvas 2 ( 3 4 onDraw: DrawScope.() -> Unit 5 ) = Spacer(modifier.drawBehind(onDraw)) 6 onDraw: DrawScope.() -> Unit @Composable 1 fun Canvas 2 ( 3 modifier: Modifier, 4 5 ) = Spacer(modifier.drawBehind(onDraw)) 6 @Composable fun Canvas ( modifier: Modifier, onDraw: DrawScope.() -> Unit ) = Spacer(modifier.drawBehind(onDraw)) 1 2 3 4 5 6 18
  43. Compose Canvas 101 DrawScope - Handles the drawing API drawRect()

    drawOval() drawLine() drawImage() drawRoundRect() drawCircle() drawArc() drawPath() fun DrawScope.drawMyShape() { } 19
  44. Compose Canvas 101 Custom View Example in Canvas Canvas(modifier =

    Modifier.fillMaxSize()) { drawCircle( color = Color.Red, radius = 300f ) drawCircle( color = Color.Green, radius = 200f ) drawCircle( color = Color.Blue, radius = 100f ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 20
  45. Compose Canvas 101 Custom View Example in Canvas Canvas(modifier =

    Modifier.fillMaxSize()) { drawCircle( color = Color.Red, radius = 300f ) drawCircle( color = Color.Green, radius = 200f ) drawCircle( color = Color.Blue, radius = 100f ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Canvas(modifier = Modifier.fillMaxSize()) { 1 drawCircle( 2 color = Color.Red, 3 radius = 300f 4 ) 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 20
  46. Compose Canvas 101 Custom View Example in Canvas Canvas(modifier =

    Modifier.fillMaxSize()) { drawCircle( color = Color.Red, radius = 300f ) drawCircle( color = Color.Green, radius = 200f ) drawCircle( color = Color.Blue, radius = 100f ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Canvas(modifier = Modifier.fillMaxSize()) { 1 drawCircle( 2 color = Color.Red, 3 radius = 300f 4 ) 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 drawCircle( color = Color.Red, radius = 300f ) Canvas(modifier = Modifier.fillMaxSize()) { 1 2 3 4 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 20
  47. Compose Canvas 101 Custom View Example in Canvas Canvas(modifier =

    Modifier.fillMaxSize()) { drawCircle( color = Color.Red, radius = 300f ) drawCircle( color = Color.Green, radius = 200f ) drawCircle( color = Color.Blue, radius = 100f ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Canvas(modifier = Modifier.fillMaxSize()) { 1 drawCircle( 2 color = Color.Red, 3 radius = 300f 4 ) 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 drawCircle( color = Color.Red, radius = 300f ) Canvas(modifier = Modifier.fillMaxSize()) { 1 2 3 4 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 drawCircle( color = Color.Green, radius = 200f ) Canvas(modifier = Modifier.fillMaxSize()) { 1 drawCircle( 2 color = Color.Red, 3 radius = 300f 4 ) 5 6 7 8 9 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 20
  48. Compose Canvas 101 Custom View Example in Canvas Canvas(modifier =

    Modifier.fillMaxSize()) { drawCircle( color = Color.Red, radius = 300f ) drawCircle( color = Color.Green, radius = 200f ) drawCircle( color = Color.Blue, radius = 100f ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Canvas(modifier = Modifier.fillMaxSize()) { 1 drawCircle( 2 color = Color.Red, 3 radius = 300f 4 ) 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 drawCircle( color = Color.Red, radius = 300f ) Canvas(modifier = Modifier.fillMaxSize()) { 1 2 3 4 5 6 drawCircle( 7 color = Color.Green, 8 radius = 200f 9 ) 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 drawCircle( color = Color.Green, radius = 200f ) Canvas(modifier = Modifier.fillMaxSize()) { 1 drawCircle( 2 color = Color.Red, 3 radius = 300f 4 ) 5 6 7 8 9 10 11 drawCircle( 12 color = Color.Blue, 13 radius = 100f 14 ) 15 } 16 Canvas(modifier = Modifier.fillMaxSize()) { drawCircle( color = Color.Red, radius = 300f ) drawCircle( color = Color.Green, radius = 200f ) drawCircle( color = Color.Blue, radius = 100f ) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 20
  49. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 A simple moving square example 21
  50. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 val animPosX = animatedFloat(initVal = 0f) @Composable 1 fun MovingSquare() { 2 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 A simple moving square example 21
  51. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 val animPosX = animatedFloat(initVal = 0f) @Composable 1 fun MovingSquare() { 2 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 5 6 7 8 9 10 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 A simple moving square example 21
  52. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 val animPosX = animatedFloat(initVal = 0f) @Composable 1 fun MovingSquare() { 2 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 5 6 7 8 9 10 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 A simple moving square example 21
  53. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 val animPosX = animatedFloat(initVal = 0f) @Composable 1 fun MovingSquare() { 2 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 5 6 7 8 9 10 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 drawRect(color = Color.Red) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 18 } 19 }) 20 } 21 A simple moving square example 21
  54. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 val animPosX = animatedFloat(initVal = 0f) @Composable 1 fun MovingSquare() { 2 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 5 6 7 8 9 10 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 drawRect(color = Color.Red) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 18 } 19 }) 20 } 21 withTransform({ translate(left = animPosX.value) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 15 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 A simple moving square example 21
  55. AnimatedValue on Canvas @Composable fun MovingSquare() { val animPosX =

    animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 val animPosX = animatedFloat(initVal = 0f) @Composable 1 fun MovingSquare() { 2 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 5 6 7 8 9 10 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 drawRect(color = Color.Red) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 withTransform({ 15 translate(left = animPosX.value) 16 }) { 17 18 } 19 }) 20 } 21 withTransform({ translate(left = animPosX.value) @Composable 1 fun MovingSquare() { 2 val animPosX = animatedFloat(initVal = 0f) 3 onActive { 4 animPosX.animateTo( 5 targetValue = 500f, 6 anim = repeatable( 7 iterations = AnimationConstants.Infinite, 8 animation = tween(durationMillis = 1000) 9 ) 10 ) 11 } 12 13 Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { 14 15 16 }) { 17 drawRect(color = Color.Red) 18 } 19 }) 20 } 21 @Composable fun MovingSquare() { val animPosX = animatedFloat(initVal = 0f) onActive { animPosX.animateTo( targetValue = 500f, anim = repeatable( iterations = AnimationConstants.Infinite, animation = tween(durationMillis = 1000) ) ) } Canvas(modifier = Modifier.preferredSize(100.dp), onDraw = { withTransform({ translate(left = animPosX.value) }) { drawRect(color = Color.Red) } }) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 A simple moving square example 21
  56. More Canvas Examples Its all about mathematics & drawing By

    Alex Lockwood github.com/alexjlockwood/bees-and-bombs-compose/ github.com/wajahatkarim3/DinoCompose 22
  57. Animations in Jetpack Compose Utilizing transitions to make solid animations

    The animateContentSize() Modifier The AnimatedVisibility Composable Single Value Animations with animate() Repeated Animations with AnimatedValue Utilizing transitions to make solid animations 23
  58. Transitions - 1 class DroidconActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DroidconEMEA2020Theme { Scaffold( topBar = { TopAppBar( /* App Bar */ ) }, floatingActionButton = { ExplodingFabButton() }, bodyContent = { // Content Composables } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 24
  59. Transitions - 1 class DroidconActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DroidconEMEA2020Theme { Scaffold( topBar = { TopAppBar( /* App Bar */ ) }, floatingActionButton = { ExplodingFabButton() }, bodyContent = { // Content Composables } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Scaffold( class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 floatingActionButton = { 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 24
  60. Transitions - 1 class DroidconActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DroidconEMEA2020Theme { Scaffold( topBar = { TopAppBar( /* App Bar */ ) }, floatingActionButton = { ExplodingFabButton() }, bodyContent = { // Content Composables } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Scaffold( class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 floatingActionButton = { 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 floatingActionButton = { class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 Scaffold( 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 24
  61. Transitions - 1 class DroidconActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DroidconEMEA2020Theme { Scaffold( topBar = { TopAppBar( /* App Bar */ ) }, floatingActionButton = { ExplodingFabButton() }, bodyContent = { // Content Composables } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Scaffold( class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 floatingActionButton = { 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 floatingActionButton = { class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 Scaffold( 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 ExplodingFabButton() class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 Scaffold( 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 floatingActionButton = { 10 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 24
  62. Transitions - 1 class DroidconActivity : AppCompatActivity() { override fun

    onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DroidconEMEA2020Theme { Scaffold( topBar = { TopAppBar( /* App Bar */ ) }, floatingActionButton = { ExplodingFabButton() }, bodyContent = { // Content Composables } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Scaffold( class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 floatingActionButton = { 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 floatingActionButton = { class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 Scaffold( 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 10 ExplodingFabButton() 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 ExplodingFabButton() class DroidconActivity : AppCompatActivity() { 1 override fun onCreate(savedInstanceState: Bundle?) { 2 super.onCreate(savedInstanceState) 3 setContent { 4 DroidconEMEA2020Theme { 5 Scaffold( 6 topBar = { 7 TopAppBar( /* App Bar */ ) 8 }, 9 floatingActionButton = { 10 11 }, 12 bodyContent = { 13 // Content Composables 14 } 15 } 16 } 17 } 18 } 19 class DroidconActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { DroidconEMEA2020Theme { Scaffold( topBar = { TopAppBar( /* App Bar */ ) }, floatingActionButton = { ExplodingFabButton() }, bodyContent = { // Content Composables } } } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 24
  63. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 25
  64. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 25
  65. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 25
  66. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeKey = FloatPropKey() enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 25
  67. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeKey = FloatPropKey() enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 25
  68. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeKey = FloatPropKey() enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabTransitionDef = transitionDefinition<FabSizeState> { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 21 } 22 25
  69. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeKey = FloatPropKey() enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabTransitionDef = transitionDefinition<FabSizeState> { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 21 } 22 state(FabSizeState.NORMAL) { state(FabSizeState.EXPLODED) { enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 25
  70. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeKey = FloatPropKey() enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabTransitionDef = transitionDefinition<FabSizeState> { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 21 } 22 state(FabSizeState.NORMAL) { state(FabSizeState.EXPLODED) { enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 this[fabSizeKey] = 80f this[fabSizeKey] = 5000f enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 19 } 20 } 21 } 22 25
  71. Transitions - 2 enum class FabSizeState { NORMAL, EXPLODED }

    val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Composable fun ExplodingFabButton() { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 7 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 22 enum class FabSizeState { NORMAL, EXPLODED } 1 2 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeKey = FloatPropKey() enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 val fabTransitionDef = transitionDefinition<FabSizeState> { } enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 this[fabSizeKey] = 5000f 19 } 20 21 } 22 state(FabSizeState.NORMAL) { state(FabSizeState.EXPLODED) { enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 13 this[fabSizeKey] = 80f 14 } 15 16 // What happens when Exploded 17 18 this[fabSizeKey] = 5000f 19 } 20 } 21 } 22 this[fabSizeKey] = 80f this[fabSizeKey] = 5000f enum class FabSizeState { 1 NORMAL, EXPLODED 2 } 3 4 val fabSizeKey = FloatPropKey() 5 6 @Composable 7 fun ExplodingFabButton() { 8 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 9 10 val fabTransitionDef = transitionDefinition<FabSizeState> { 11 // What happens when Normal 12 state(FabSizeState.NORMAL) { 13 14 } 15 16 // What happens when Exploded 17 state(FabSizeState.EXPLODED) { 18 19 } 20 } 21 } 22 enum class FabSizeState { NORMAL, EXPLODED } val fabSizeKey = FloatPropKey() @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { // What happens when Normal state(FabSizeState.NORMAL) { this[fabSizeKey] = 80f } // What happens when Exploded state(FabSizeState.EXPLODED) { this[fabSizeKey] = 5000f } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 25
  72. Transitions - 3 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 26
  73. Transitions - 3 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /* ---- States from Previous Slide ---- */ @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 26
  74. Transitions - 3 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /* ---- States from Previous Slide ---- */ @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 8 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 18 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 26
  75. Transitions - 3 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /* ---- States from Previous Slide ---- */ @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 8 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 18 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 10 11 12 13 14 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 26
  76. Transitions - 3 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /* ---- States from Previous Slide ---- */ @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 8 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 18 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 10 11 12 13 14 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 20 21 } 22 } 23 } 24 26
  77. Transitions - 3 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 /* ---- States from Previous Slide ---- */ @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 8 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 18 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 10 11 12 13 14 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 fabSizeKey using tween(durationMillis = 1000, 20 easing = FastOutSlowInEasing) 21 } 22 } 23 } 24 fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 // Transition from Normal to Exploded 8 transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { 9 fabSizeKey using keyframes { 10 durationMillis = 1000 11 80f at 0 12 35f at 200 13 5000f at 1000 14 } 15 } 16 17 // Transition from Exploded to Normal 18 transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { 19 20 21 } 22 } 23 } 24 @Composable fun ExplodingFabButton() { val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ // Transition from Normal to Exploded transition(FabSizeState.NORMAL to FabSizeState.EXPLODED) { fabSizeKey using keyframes { durationMillis = 1000 80f at 0 35f at 200 5000f at 1000 } } // Transition from Exploded to Normal transition(FabSizeState.EXPLODED to FabSizeState.NORMAL) { fabSizeKey using tween(durationMillis = 1000, easing = FastOutSlowInEasing) } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 26
  78. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 27
  79. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 6 7 8 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 27
  80. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 6 7 8 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val transitionState = transition( @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 27
  81. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 6 7 8 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val transitionState = transition( @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabTransitionDef = transitionDefinition<FabSizeState> { definition = fabTransitionDef, @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 27
  82. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 6 7 8 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val transitionState = transition( @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabTransitionDef = transitionDefinition<FabSizeState> { definition = fabTransitionDef, @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } initState = fabSizeState.value, @Composable 1 fun ExplodingFabButton() { 2 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 27
  83. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 6 7 8 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val transitionState = transition( @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabTransitionDef = transitionDefinition<FabSizeState> { definition = fabTransitionDef, @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } initState = fabSizeState.value, @Composable 1 fun ExplodingFabButton() { 2 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 14 15 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 27
  84. Transitions - 4 @Composable fun ExplodingFabButton() { val fabSizeState =

    remember { mutableStateOf(FabSizeState.NORMAL) } val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } val transitionState = transition( definition = fabTransitionDef, initState = fabSizeState.value, toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL ) FabButton(fabSizeState = fabSizeState, transitionState = transitionState) } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val fabTransitionDef = transitionDefinition<FabSizeState> { /* ---- States from Previous Slide ---- */ /* ---- Transitions from Previous Slide ---- */ } @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 6 7 8 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val transitionState = transition( @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabTransitionDef = transitionDefinition<FabSizeState> { definition = fabTransitionDef, @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } initState = fabSizeState.value, @Composable 1 fun ExplodingFabButton() { 2 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 toState = if (fabSizeState.value == FabSizeState.NORMAL) FabSizeState.EXPLODED else FabSizeState.NORMAL @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 14 15 16 ) 17 18 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) 19 } 20 FabButton(fabSizeState = fabSizeState, transitionState = transitionState) @Composable 1 fun ExplodingFabButton() { 2 val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) } 3 4 val fabTransitionDef = transitionDefinition<FabSizeState> { 5 /* ---- States from Previous Slide ---- */ 6 7 /* ---- Transitions from Previous Slide ---- */ 8 } 9 10 val transitionState = transition( 11 definition = fabTransitionDef, 12 initState = fabSizeState.value, 13 toState = if (fabSizeState.value == FabSizeState.NORMAL) 14 FabSizeState.EXPLODED 15 else FabSizeState.NORMAL 16 ) 17 18 19 } 20 27
  85. Transitions - 5 @Composable fun ExplodingFabButton() { /* From Previous

    Slides */ } @Composable fun FabButton(fabSizeState: MutableState<FabSizeState>, transitionState: TransitionState ) { FloatingActionButton( onClick = { }, modifier = Modifier.size(transitionState[fabSizeKey].dp) ) { Icon(asset = Icons.Default.Add) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 28
  86. Transitions - 5 @Composable fun ExplodingFabButton() { /* From Previous

    Slides */ } @Composable fun FabButton(fabSizeState: MutableState<FabSizeState>, transitionState: TransitionState ) { FloatingActionButton( onClick = { }, modifier = Modifier.size(transitionState[fabSizeKey].dp) ) { Icon(asset = Icons.Default.Add) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun ExplodingFabButton() { /* From Previous Slides */ } @Composable 1 2 3 4 5 @Composable 6 fun FabButton(fabSizeState: MutableState<FabSizeState>, 7 transitionState: TransitionState 8 ) { 9 FloatingActionButton( 10 onClick = { }, 11 modifier = Modifier.size(transitionState[fabSizeKey].dp) 12 ) { 13 Icon(asset = Icons.Default.Add) 14 } 15 } 16 28
  87. Transitions - 5 @Composable fun ExplodingFabButton() { /* From Previous

    Slides */ } @Composable fun FabButton(fabSizeState: MutableState<FabSizeState>, transitionState: TransitionState ) { FloatingActionButton( onClick = { }, modifier = Modifier.size(transitionState[fabSizeKey].dp) ) { Icon(asset = Icons.Default.Add) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun ExplodingFabButton() { /* From Previous Slides */ } @Composable 1 2 3 4 5 @Composable 6 fun FabButton(fabSizeState: MutableState<FabSizeState>, 7 transitionState: TransitionState 8 ) { 9 FloatingActionButton( 10 onClick = { }, 11 modifier = Modifier.size(transitionState[fabSizeKey].dp) 12 ) { 13 Icon(asset = Icons.Default.Add) 14 } 15 } 16 fun FabButton(fabSizeState: MutableState<FabSizeState>, FloatingActionButton( Icon(asset = Icons.Default.Add) @Composable 1 fun ExplodingFabButton() { 2 /* From Previous Slides */ 3 } 4 5 @Composable 6 7 transitionState: TransitionState 8 ) { 9 10 onClick = { }, 11 modifier = Modifier.size(transitionState[fabSizeKey].dp) 12 ) { 13 14 } 15 } 16 28
  88. Transitions - 5 @Composable fun ExplodingFabButton() { /* From Previous

    Slides */ } @Composable fun FabButton(fabSizeState: MutableState<FabSizeState>, transitionState: TransitionState ) { FloatingActionButton( onClick = { }, modifier = Modifier.size(transitionState[fabSizeKey].dp) ) { Icon(asset = Icons.Default.Add) } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fun ExplodingFabButton() { /* From Previous Slides */ } @Composable 1 2 3 4 5 @Composable 6 fun FabButton(fabSizeState: MutableState<FabSizeState>, 7 transitionState: TransitionState 8 ) { 9 FloatingActionButton( 10 onClick = { }, 11 modifier = Modifier.size(transitionState[fabSizeKey].dp) 12 ) { 13 Icon(asset = Icons.Default.Add) 14 } 15 } 16 fun FabButton(fabSizeState: MutableState<FabSizeState>, FloatingActionButton( Icon(asset = Icons.Default.Add) @Composable 1 fun ExplodingFabButton() { 2 /* From Previous Slides */ 3 } 4 5 @Composable 6 7 transitionState: TransitionState 8 ) { 9 10 onClick = { }, 11 modifier = Modifier.size(transitionState[fabSizeKey].dp) 12 ) { 13 14 } 15 } 16 transitionState: TransitionState modifier = Modifier.size(transitionState[fabSizeKey].dp) @Composable 1 fun ExplodingFabButton() { 2 /* From Previous Slides */ 3 } 4 5 @Composable 6 fun FabButton(fabSizeState: MutableState<FabSizeState>, 7 8 ) { 9 FloatingActionButton( 10 onClick = { }, 11 12 ) { 13 Icon(asset = Icons.Default.Add) 14 } 15 } 16 28
  89. Transitions - Examples By Joe Birch By Ray Wenderlich https://joebirch.co/

    https://www.raywenderlich.com/13282144-jetpack-compose- animations-tutorial-getting-started By Myself 29
  90. Resources Alex Lockwood https://github.com/alexjlockwood/bees-and-bombs-compose https://github.com/alexjlockwood/android-2048-compose Joe Birch https://joebirch.co/exploring-jetpack-compose/ Gurupreet Singh

    https://github.com/Gurupreet/ComposeCookBook Leland Richardson https://www.twitch.tv/intelligibabble Official by Google https://developer.android.com/courses/pathways/compose Vinay Gaba https://github.com/vinaygaba/Learn-Jetpack-Compose-By-Example 30