Skip to content

sagar-viradiya/koreography

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

30 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Koreography

Choreograph your Compose Animation πŸ’ƒπŸ•Ί

Maven Central

Github Followers Twitter Follow


A lightweight Compose Animation utility library to choreograph low-level Animation API (https://developer.android.com/jetpack/compose/animation#animation) through Kotlin DSL. It does the heavy lifting of dealing with coroutines under the hood so that you can focus on your animation choreography.

Including in your project

Koreography is available on mavenCentral()

implementation 'io.github.sagar-viradiya:koreography:0.3.0'

Usage

Creating choreography is the process of recording moves on Animatable, A low level compose animation API. Moves could be either parallel or sequential. A choreography is a composition of such moves that you can declare through clean and concise Kotlin DSL as shown below.

For example, let's say you want to sequentially animate alpha first and then scale of an image then you can declare the following choreography. You would then apply animatable values that you are animating in choreography in the Image composable as shown below.

Choreographying sequential animation

val alphaAnimatable = remember {
    Animatable(0f)
}

val scaleAnimatable = remember {
    Animatable(0f)
}

val koreography = rememberKoreography {
    move(
        animatable = alphaAnimatable,
        targetValue = 1f,
        animationSpec = tween(500)
    )
    
    move(
        animatable = scaleAnimatable,
        targetValue = 2f,
        animationSpec = tween(500)
    )
}
.
.
.
Image(
    modifier = Modifier.graphicsLayer {
        alpha = alphaAnimatable.value
        scaleX = scaleAnimatable.value
    }, 
    painter = painterResource(id = R.drawable.image)
)

Choreographying parallel animation

Let's say you want to parallelly animate alpha and scale of an image then you can declare the following choreography.

val alphaAnimatable = remember {
    Animatable(0f)
}

val scaleAnimatable = remember {
    Animatable(0f)
}

val koreography = rememberKoreography {
    parallelMoves {
        move(
            animatable = alphaAnimatable,
            targetValue = 1f,
            animationSpec = tween(500)
        )
        
        move(
            animatable = scaleAnimatable,
            targetValue = 2f,
            animationSpec = tween(500)
        )
    }
}
.
.
.
Image(
    modifier = Modifier.graphicsLayer {
        alpha = alphaAnimatable.value
        scaleX = scaleAnimatable.value
    }, 
    painter = painterResource(id = R.drawable.image)
)

Complex choreography

You can have a nested hierarchy of moves to create complex choreography. The example below has three animations running parallelly and out of them, the last one has two animations within running sequentially.

val alphaAnimatable = remember {
    Animatable(0f)
}

val scaleAnimatable = remember {
    Animatable(0f)
}

val rotationAnimatable = remember {
    Animatable(0f)
}

val translationXAnimatable = remember {
    Animatble(0f)
}

val koreography = rememberKoreography {
    parallelMoves {
        move(
            animatable = alphaAnimatable,
            targetValue = 1f,
            animationSpec = tween(500)
        )
        
        move(
            animatable = scaleAnimatable,
            targetValue = 2f,
            animationSpec = tween(500)
        )
        
        sequentialMoves {
            move(
                animatable = rotationAnimatable,
                targetValue = 20f,
                animationSpec = tween(500)
            )
            
            move(
                animatable = translationXAnimatable,
                targetValue = 200f,
                animationSpec = tween(500)
            )
        }
    }
}
.
.
.
Image(
    modifier = Modifier.graphicsLayer {
        alpha = alphaAnimatable.value
        scaleX = scaleAnimatable.value
        translationX = translationXAnimatable.value
        rotationZ = rotationAnimatable.value
    }, 
    painter = painterResource(id = R.drawable.image)
)

Executing choreography

Once choreography is ready it's time to dance! πŸ’ƒπŸ•Ί.

One time dance

You can execute the choreography once by calling dance function. If you wish to get callback after execution of choreography then you can pass trailing lambda.

koreography.dance(scope = coroutineScope) {
    // onDanceFinished : Optional trailing lambda
}

Repeat dance

You can execute the choreography multiple times by calling repeatDance function. Following call executes choreography three times.

koreography.repeatDance(count = 3, scope = coroutineScope) {
    // onDanceFinished : Optional trailing lambda
}

Infinite dance

You can execute the choreography forever until composition is alive.

koreography.danceForever(scope = coroutineScope){
    // onDanceFinished : Optional trailing lambda
}

Please note the coroutineScope should be obtained through rememberCoroutineScope(). Make sure you pass coroutine scope which will get cleared once you exit composition.

Executing choreography based on state change πŸš€

Executing choreography based on state change is also supported. This API is similar to LaunchedEffect API of compose side effects.

In the following example, we are executing choreography passed in the trailing lambda of LaunchKoreography composable on a state value change. Choreography contains two animations that will be executed sequentially.

val alphaAnimatable = remember {
    Animatable(0f)
}

val scaleAnimatable = remember {
    Animatable(0f)
}

LaunchKoreography(state) {
    move(
        animatbale = alphaAnimatable,
        targetValue = 1f,
        animationSpec = tween(500)
    )
    
    move(
        animatbale = scaleAnimatable,
        targetValue = 2f,
        animationSpec = tween(500)
    )
}
.
.
.
Image(
    modifier = Modifier.graphicsLayer {
        alpha = alphaAnimatable.value
        scaleX = scaleAnimatable.value
    }, 
    painter = painterResource(id = R.drawable.image)
)

Samples

There is endless possibilities with power of coroutines and compose animation API! Here are some free lottie animations recreated using koreography. You can find the source code in the sample app.

screen-20230611-113322.2.mov
screen-20230611-113358.3.mp4
screen-20230611-113420.2.mp4
screen-20230611-113444.2.mov
meditaion_animation.mov

Contribution

This is the early preview and unfortunately it is not ready to accept any contribution yet. Once this is stable enough contribution guidelines will be updated here. Meanwhile feel free to start GitHub Discussions for feature request and improvements.

License

Copyright 2022 Koreography Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

A light weight Compose Animation library to choreograph low level Animation API through Kotlin DSL.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages