android-native
Skill7 starsChanged 10 months agoMITView on GitHub
Android native animation using Jetpack Compose, View animations, and Material Motion. Use when targeting Android apps with native performance and Material Design compliance.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- MathiasPaulenko/ai-toolkittheir own version, first seen Oct 8, 2026
- BuilderIO/builder-agent-skillstheir own version, first seen May 26, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- BuilderIO/builder-agent-skills★ 16same name
- MathiasPaulenko/ai-toolkit★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository87 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- motion-designSkill
- 3d-transformsSkill
- accessibilitySkill
- animation-recipesSkill
- anticipationSkill
- arc-motionSkill
- attention-choreographySkill
- attentionSkill
- audio-reactiveSkill
- blurSkill
- brand-animationSkill
- cameraSkill
- characterSkill
- choice-resolutionSkill
- cinematicSkill
- code-generationSkill
- colorSkill
- component-animationsSkill
- compositingSkill
- consequenceSkill
- container-transformSkill
- css-advancedSkill
- data-visualizationSkill
- depthSkill
- distortionSkill
- dramaturgySkill
- durationSkill
- easingSkill
- emotional-journeySkill
- emotion-mappingSkill
- emotion-selectionSkill
- empty-statesSkill
- entrance-patternsSkill
- exaggerationSkill
- exit-patternsSkill
- exportSkill
- figma-integrationSkill
- follow-throughSkill
- frame-timingSkill
- gesture-motionSkill
- glow-shadowSkill
- intentSkill
- ios-nativeSkill
- loading-statesSkill
- loopingSkill
- lottieSkill
- masksSkill
- microstateSkill
- morphingSkill
- motion-auditSkill
- motion-blurSkill
- motion-principlesSkill
- motion-specsSkill
- narrative-arcSkill
- notificationsSkill
- onboardingSkill
- opacitySkill
- orchestratorSkill
- particlesSkill
- The first 60 shown.
The file
Files
Android Native Animation
Native Android animation APIs aligned with Material Design 3 motion system.
API Selection
| API | Use Case | M3 Support |
| Jetpack Compose | Modern declarative UI | Excellent |
| ObjectAnimator | View system animations | Good |
| ViewPropertyAnimator | Simple view animations | Good |
| Material Transitions | M3 container transform | Native |
| MotionLayout | Complex choreography | Good |
Jetpack Compose Animation
Basic Animation
// Animate state changes
var expanded by remember { mutableStateOf(false) }
val size by animateDpAsState(
targetValue = if (expanded) 200.dp else 100.dp,
animationSpec = spring(
dampingRatio = 0.9f,
stiffness = Spring.StiffnessMedium
)
)
Box(modifier = Modifier.size(size))M3 Spring Presets
object M3Springs {
// Fast spatial (small elements)
val fastSpatial = spring<Float>(
dampingRatio = 0.9f,
stiffness = 1400f
)
// Default spatial (standard UI)
val defaultSpatial = spring<Float>(
dampingRatio = 0.9f,
stiffness = 700f
)
// Slow spatial (large elements)
val slowSpatial = spring<Float>(
dampingRatio = 0.9f,
stiffness = 300f
)
// Effects (opacity, color - no overshoot)
val fastEffects = spring<Float>(
dampingRatio = 1.0f,
stiffness = 3800f
)
val defaultEffects = spring<Float>(
dampingRatio = 1.0f,
stiffness = 1600f
)
}AnimatedContent
AnimatedContent(
targetState = currentScreen,
transitionSpec = {
// M3 shared axis transition
slideInHorizontally { width -> width } + fadeIn() with
slideOutHorizontally { width -> -width } + fadeOut()
}
) { screen ->
when (screen) {
Screen.Home -> HomeScreen()
Screen.Detail -> DetailScreen()
}
}AnimatedVisibility
AnimatedVisibility(
visible = isVisible,
enter = fadeIn(animationSpec = tween(300)) +
scaleIn(initialScale = 0.95f),
exit = fadeOut(animationSpec = tween(200)) +
scaleOut(targetScale = 0.95f)
) {
Card { /* content */ }
}Transition Animation
val transition = updateTransition(targetState = selected)
val scale by transition.animateFloat(
transitionSpec = { spring(dampingRatio = 0.9f, stiffness = 700f) }
) { state ->
if (state) 1.1f else 1.0f
}
val color by transition.animateColor(
transitionSpec = { spring(dampingRatio = 1.0f, stiffness = 1600f) }
) { state ->
if (state) MaterialTheme.colorScheme.primary else Color.Gray
}Material 3 Transitions
Container Transform
// Using accompanist-navigation-material
NavHost(navController) {
composable("list") {
ItemList(onItemClick = { item ->
navController.navigate("detail/${item.id}")
})
}
composable(
"detail/{id}",
enterTransition = {
fadeIn(animationSpec = tween(300)) +
scaleIn(initialScale = 0.9f)
},
exitTransition = {
fadeOut(animationSpec = tween(200)) +
scaleOut(targetScale = 0.9f)
}
) {
DetailScreen()
}
}Shared Element (Compose 1.7+)
SharedTransitionLayout {
AnimatedContent(targetState = showDetail) { show ->
if (show) {
DetailScreen(
Modifier.sharedElement(
rememberSharedContentState(key = "image"),
animatedVisibilityScope = this@AnimatedContent
)
)
} else {
ListScreen(
Modifier.sharedElement(
rememberSharedContentState(key = "image"),
animatedVisibilityScope = this@AnimatedContent
)
)
}
}
}View System (Legacy)
ObjectAnimator
// M3 standard easing
val translateAnim = ObjectAnimator.ofFloat(view, "translationY", 0f, 100f).apply {
duration = 300
interpolator = PathInterpolator(0.2f, 0f, 0f, 1f) // M3 standard
}
// M3 emphasized two-segment path
val emphasizedPath = Path().apply {
moveTo(0f, 0f)
cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f)
cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f)
}
val emphasizedInterpolator = PathInterpolator(emphasizedPath)ViewPropertyAnimator
view.animate()
.translationY(100f)
.alpha(1f)
.setDuration(300)
.setInterpolator(PathInterpolator(0.05f, 0.7f, 0.1f, 1f)) // emphasized-decelerate
.start()SpringAnimation (AndroidX)
val springAnim = SpringAnimation(view, DynamicAnimation.TRANSLATION_Y).apply {
spring = SpringForce().apply {
dampingRatio = 0.9f // M3 spatial
stiffness = 700f // M3 default
}
}
springAnim.animateToFinalPosition(100f)M3 Timing Functions
object M3Interpolators {
// Standard (most animations)
val standard = PathInterpolator(0.2f, 0f, 0f, 1f)
// Emphasized-decelerate (entrances)
val emphasizedDecelerate = PathInterpolator(0.05f, 0.7f, 0.1f, 1f)
// Emphasized-accelerate (exits)
val emphasizedAccelerate = PathInterpolator(0.3f, 0f, 0.8f, 0.15f)
// Standard-decelerate
val standardDecelerate = PathInterpolator(0f, 0f, 0f, 1f)
// Exact M3 emphasized (two-segment path)
val emphasized: Interpolator by lazy {
PathInterpolator(Path().apply {
moveTo(0f, 0f)
cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f)
cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f)
})
}
}Duration Scale
| Token | Android Duration | Use |
short-1 | 50ms | Micro-interactions |
short-4 | 200ms | Buttons, FAB |
medium-2 | 300ms | Dialogs, bottom sheets |
long-2 | 500ms | Page transitions |
extra-long-4 | 1000ms | Hero moments |
Reduced Motion
// Check user preference
val reduceMotion = ViewCompat.isAccessibilityReduceMotionEnabled(context)
// Compose
val reduceMotion = LocalReduceMotion.current
@Composable
fun AnimatedBox(visible: Boolean) {
val reduceMotion = LocalReduceMotion.current
AnimatedVisibility(
visible = visible,
enter = if (reduceMotion) fadeIn() else fadeIn() + scaleIn(),
exit = if (reduceMotion) fadeOut() else fadeOut() + scaleOut()
) {
Box()
}
}Haptic Feedback
// Pair with animations
val view = LocalView.current
fun onButtonPress() {
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
// Trigger animation
}
// Compose
val haptic = LocalHapticFeedback.current
haptic.performHapticFeedback(HapticFeedbackType.LongPress)Lottie Integration
// Compose
val composition by rememberLottieComposition(
LottieCompositionSpec.RawRes(R.raw.animation)
)
val progress by animateLottieCompositionAsState(
composition,
iterations = LottieConstants.IterateForever
)
LottieAnimation(
composition = composition,
progress = { progress }
)Related Skills
- Dependencies: easing, duration, spring
- See also: platform-adaptation, accessibility, lottie
- Tokens:
tokens/android-motion.tokens.json
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

