A powerful Kotlin Multiplatform animation library for Jetpack Compose with 90+ ready-to-use animations inspired by animate.css.
- ๐จ 90+ Pre-built Animations - Attention seekers, entrances, exits, and special effects
- ๐ Simple API - Just wrap your composables with
Animated()
- ๐ฏ Keyframe-based - Smooth, natural animations with custom easing
- ๐ฑ Multiplatform - Works on Android, iOS, Desktop, and Web
- โก Performant - Optimized for Compose with minimal overhead
- ๐ Customizable - Create your own animation presets
- ๐ฎ Interactive Playground - Test and configure animations in real-time
Add the dependency to your module's build.gradle.kts
:
dependencies {
implementation("com.nomanr:animate-compose:${version}")
}
import com.nomanr.animate.compose.animated.Animated
import com.nomanr.animate.compose.presets.fadeinentrances.FadeIn
@Composable
fun MyComponent() {
Animated(
preset = FadeIn(),
durationMillis = 1000
) {
Text("Hello, Animated World!")
}
}
See the complete list of animations for detailed descriptions of all 90+ animations.
Perfect for drawing user attention to important elements.
Animated(preset = Bounce()) { Icon(...) }
Animated(preset = Flash()) { Button(...) }
Animated(preset = Pulse()) { Card(...) }
Animated(preset = RubberBand()) { Text(...) }
Animated(preset = ShakeX()) { TextField(...) }
Animated(preset = Swing()) { Image(...) }
Animated(preset = Tada()) { Box(...) }
Smooth ways to introduce elements to the screen.
// Fade entrances
Animated(preset = FadeIn()) { ... }
Animated(preset = FadeInDown()) { ... }
Animated(preset = FadeInLeft()) { ... }
Animated(preset = FadeInRight()) { ... }
Animated(preset = FadeInUp()) { ... }
// Bounce entrances
Animated(preset = BounceIn()) { ... }
Animated(preset = BounceInDown()) { ... }
Animated(preset = BounceInLeft()) { ... }
// Slide entrances
Animated(preset = SlideInDown()) { ... }
Animated(preset = SlideInLeft()) { ... }
// Zoom entrances
Animated(preset = ZoomIn()) { ... }
Animated(preset = ZoomInDown()) { ... }
// And many more...
Graceful ways to remove elements from the screen.
Animated(preset = FadeOut(), animateOnEnter = false) { ... }
Animated(preset = BounceOut(), animateOnEnter = false) { ... }
Animated(preset = SlideOutUp(), animateOnEnter = false) { ... }
Animated(preset = ZoomOut(), animateOnEnter = false) { ... }
Unique animations for memorable interactions.
Animated(preset = Hinge()) { ... }
Animated(preset = JackInTheBox()) { ... }
Animated(preset = RollIn()) { ... }
Animated(preset = RollOut()) { ... }
val animatedState = rememberAnimatedState()
Animated(
preset = FadeIn(),
state = animatedState
) {
Card { ... }
}
// Control the animation
LaunchedEffect(someCondition) {
animatedState.animate()
}
val animatedState = rememberAnimatedState()
// Check animation state
val isAnimating = animatedState.isAnimating.value
val isFinished = animatedState.isAnimationFinished.value
Animated(
preset = BounceIn(),
state = animatedState
) {
Box { ... }
}
// Trigger animation manually
Button(onClick = { animatedState.animate() }) {
Text("Animate")
}
Animated(
preset = Pulse(),
repeat = true,
durationMillis = 1000
) {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = "Pulsing heart"
)
}
Create your own animation presets by extending AnimationPreset
:
class MyCustomAnimation : AnimationPreset {
override val name = "MyCustomAnimation"
override val durationMillis = 800
override fun createKeyframes(containerSize: ContainerSize): List<Keyframe> {
return listOf(
Keyframe.static(0f, alpha = 0f, scale = 0.3f),
Keyframe.segment(
0f to 0.5f,
alpha = SegmentFloat(0f, 1f),
scale = SegmentFloat(0.3f, 1.05f),
easing = Easing.EaseOutCubic
),
Keyframe.segment(
0.5f to 1f,
scale = SegmentFloat(1.05f, 1f),
easing = Easing.EaseInOutCubic
)
)
}
}
Platform | Status | Notes |
---|---|---|
Android | โ Stable | Full support |
iOS | โ Stable | Via Skiko |
Desktop | โ Stable | Via Skiko |
Web | โ Stable | Via Skiko |
- Reuse Animation Presets: Create preset instances once and reuse them
- Avoid Excessive Layers: Complex animations on deeply nested composables may impact performance
- Use
animateOnEnter
: Set tofalse
for exit animations to avoid unnecessary initial animations - Profile Your Animations: Use the built-in playground to test performance with your specific use cases
Explore all animations in our interactive playground:
# Clone the repository
git clone https://github.com/yourusername/animate-compose.git
The sample app includes:
- Visual catalog of all animations
- Interactive configuration options
- Code generation for custom presets
./gradlew :sample:app:android:installDebug
# or
./gradlew :sample:app:android:assembleDebug
# Open the project in Xcode
open sample/app/ios/iosApp.xcodeproj
# Or build from command line
cd sample/app/ios
xcodebuild -scheme iosApp -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 15'
./gradlew :sample:app:desktop:run
# Development server with hot reload
./gradlew :sample:app:web:jsBrowserDevelopmentRun
# Production build
./gradlew :sample:app:web:jsBrowserProductionWebpack
We welcome contributions! Please see our Contributing Guide for details.
- Create a new class extending
AnimationPreset
- Define keyframes using the keyframe DSL
- Place it in the appropriate category package
- Add tests and documentation
This project is licensed under the Apache License 2.0 - see the LICENSE.txt file for details.