$30 off During Our Annual Pro Sale. View Details »

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

    View Slide

  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

    View Slide

  3. Made with Jetpack Compose
    Alex Lockwood Gurupreet Singh
    3

    View Slide

  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
    4

    View Slide

  5. 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

    View Slide

  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
    6

    View Slide

  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
    6

    View Slide

  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
    6

    View Slide

  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
    6

    View Slide

  10. 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

    View Slide

  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
    7

    View Slide

  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
    7

    View Slide

  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
    7

    View Slide

  14. 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

    View Slide

  15. 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

    View Slide

  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
    9

    View Slide

  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
    9

    View Slide

  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
    9

    View Slide

  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
    9

    View Slide

  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)
    ) {
    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

    View Slide

  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
    Default
    Enter
    Enter + Exit
    10

    View Slide

  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
    Default
    Enter
    Enter + Exit
    10

    View Slide

  23. 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

    View Slide

  24. AnimatedVisbility Composable
    cs.android.com
    AnimatedVisibility in LazyColumn
    AnimatedVisibility in multiple Composables
    11

    View Slide

  25. 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

    View Slide

  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
    The animate()
    A simple method for animations between current and target state.
    Supports Int, Dp, Color, Rect and many more types.
    13

    View Slide

  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
    The animate()
    A simple method for animations between current and target state.
    Supports Int, Dp, Color, Rect and many more types.
    13

    View Slide

  28. @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

    View Slide

  29. @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

    View Slide

  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
    The animate()
    14

    View Slide

  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
    The animate()
    14

    View Slide

  32. @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

    View Slide

  33. @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

    View Slide

  34. Examples of animate()
    By Gurupreet Singh
    github.com/Gurupreet/ComposeCookBook
    15

    View Slide

  35. 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

    View Slide

  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
    Repeated Animations with AnimatedValue
    17

    View Slide

  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
    Repeated Animations with AnimatedValue
    17

    View Slide

  38. @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

    View Slide

  39. @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

    View Slide

  40. @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

    View Slide

  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
    18

    View Slide

  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
    18

    View Slide

  43. 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

    View Slide

  44. 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

    View Slide

  45. 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

    View Slide

  46. Compose Canvas 101
    DrawScope - Handles the drawing API
    drawRect() drawOval() drawLine() drawImage()
    drawRoundRect() drawCircle() drawArc() drawPath()
    fun DrawScope.drawMyShape() { }
    19

    View Slide

  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
    20

    View Slide

  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
    20

    View Slide

  49. 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

    View Slide

  50. 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

    View Slide

  51. 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

    View Slide

  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
    A simple moving square example
    21

    View Slide

  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
    A simple moving square example
    21

    View Slide

  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
    A simple moving square example
    21

    View Slide

  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
    A simple moving square example
    21

    View Slide

  56. 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

    View Slide

  57. 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

    View Slide

  58. 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

    View Slide

  59. More Canvas Examples
    Its all about mathematics & drawing
    By Alex Lockwood
    github.com/alexjlockwood/bees-and-bombs-compose/
    github.com/wajahatkarim3/DinoCompose
    22

    View Slide

  60. 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

    View Slide

  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
    24

    View Slide

  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
    24

    View Slide

  63. 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

    View Slide

  64. 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

    View Slide

  65. 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

    View Slide

  66. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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

    View Slide

  67. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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

    View Slide

  68. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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

    View Slide

  69. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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 {
    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

    View Slide

  70. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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 {
    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 {
    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

    View Slide

  71. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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 {
    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 {
    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 {
    }
    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

    View Slide

  72. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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 {
    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 {
    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 {
    }
    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 {
    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

    View Slide

  73. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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 {
    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 {
    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 {
    }
    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 {
    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 {
    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

    View Slide

  74. Transitions - 2
    enum class FabSizeState {
    NORMAL, EXPLODED
    }
    val fabSizeKey = FloatPropKey()
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    // 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 {
    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 {
    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 {
    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 {
    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 {
    }
    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 {
    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 {
    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 {
    // 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

    View Slide

  75. Transitions - 3
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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

    View Slide

  76. Transitions - 3
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    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

    View Slide

  77. Transitions - 3
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    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 {
    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

    View Slide

  78. Transitions - 3
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    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 {
    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 {
    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

    View Slide

  79. Transitions - 3
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    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 {
    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 {
    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 {
    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

    View Slide

  80. Transitions - 3
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    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 {
    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 {
    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 {
    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 {
    /* ---- 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

    View Slide

  81. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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

    View Slide

  82. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    /* ---- 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

    View Slide

  83. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    /* ---- 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 {
    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

    View Slide

  84. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    /* ---- 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 {
    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 {
    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

    View Slide

  85. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    /* ---- 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 {
    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 {
    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 {
    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

    View Slide

  86. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    /* ---- 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 {
    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 {
    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 {
    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 {
    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

    View Slide

  87. Transitions - 4
    @Composable
    fun ExplodingFabButton() {
    val fabSizeState = remember { mutableStateOf(FabSizeState.NORMAL) }
    val fabTransitionDef = transitionDefinition {
    /* ---- 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 {
    /* ---- 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 {
    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 {
    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 {
    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 {
    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 {
    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

    View Slide

  88. Transitions - 5
    @Composable
    fun ExplodingFabButton() {
    /* From Previous Slides */
    }
    @Composable
    fun FabButton(fabSizeState: MutableState,
    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

    View Slide

  89. Transitions - 5
    @Composable
    fun ExplodingFabButton() {
    /* From Previous Slides */
    }
    @Composable
    fun FabButton(fabSizeState: MutableState,
    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,
    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

    View Slide

  90. Transitions - 5
    @Composable
    fun ExplodingFabButton() {
    /* From Previous Slides */
    }
    @Composable
    fun FabButton(fabSizeState: MutableState,
    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,
    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,
    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

    View Slide

  91. Transitions - 5
    @Composable
    fun ExplodingFabButton() {
    /* From Previous Slides */
    }
    @Composable
    fun FabButton(fabSizeState: MutableState,
    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,
    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,
    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,
    7
    8
    ) {
    9
    FloatingActionButton(
    10
    onClick = { },
    11
    12
    ) {
    13
    Icon(asset = Icons.Default.Add)
    14
    }
    15
    }
    16
    28

    View Slide

  92. 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

    View Slide

  93. 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

    View Slide

  94. Thank You for Listening!
    Code is available at
    https://github.com/wajahatkarim3/droidcon2020
    WajahatKarim
    wajahatkarim.com/subscribe
    wajahatkarim.com
    31

    View Slide