Tuesday, April 13, 2021

jetpack compose - Keyframes animation

MainActivity.kt

package com.cfsuman.jetpackcompose

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Fireplace
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MainContent()
        }
    }


    @Composable
    fun MainContent(){
        val isOpaque = remember { mutableStateOf(value = true) }
        val result = remember { mutableStateOf("") }
        val isEnabled = remember { mutableStateOf(true)}

        val alpha: Float by animateFloatAsState(
            targetValue = if (isOpaque.value) 1f else 0.1f,

            // keyframes animation is based on the snapshot values
            // and specified at different timestamps
            animationSpec = keyframes {
                durationMillis = 3500
                0.0f at 0 with LinearOutSlowInEasing // for 0-500 ms
                0.2f at 500 with FastOutLinearInEasing // for 500-1000 ms
                0.4f at 1000 with LinearEasing
                0.6f at 1750 // ms
                0.8f at 2500 with FastOutSlowInEasing // for 2500-3000 ms
                0.8f at 3000 // ms
            },
            // animation finished listener
            finishedListener = {
                result.value = "Finished at alpha $it"
                isEnabled.value = true
            }
        )

        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color(0xFFFAD6A5))
                .padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Button(
                onClick = {
                    isOpaque.value = !isOpaque.value
                    isEnabled.value = false
                },
                colors = ButtonDefaults.buttonColors(
                    Color(0xFF8A3324), Color(0xCCFFFFFF)
                ),
                enabled = isEnabled.value
            ) {
                Text(
                    text = "Animate Opacity",
                    modifier = Modifier.padding(12.dp)
                )
            }

            Icon(
                Icons.Filled.Fireplace,
                "Localized description",
                tint = Color(0xFFE03C31),
                modifier = Modifier
                    .size(300.dp)
                    .alpha(alpha = alpha)
            )

            Text(
                text = result.value,
                fontSize = 25.sp,
                fontWeight = FontWeight.Bold,
                fontFamily = FontFamily.Cursive
            )
        }
    }


    @Preview
    @Composable
    fun ComposablePreview(){
        //MainContent()
    }
}