[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-148":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":14,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":21,"hasPages":21,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":33,"readmeContent":34,"aiSummary":35,"trendingCount":15,"starSnapshotCount":15,"syncStatus":36,"lastSyncTime":37,"discoverSource":38},148,"compose-animations","skydoves\u002Fcompose-animations","skydoves","⚡️ A collection of Jetpack Compose animations for the best practices. Tweak literals at the top of any file, save, and watch the motion morph in real-time.","https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations",null,"Kotlin",232,11,3,0,6,45,9,3.24,"Apache License 2.0",false,"main",[24,25,26,27,28,29,30,31,32,7],"android","animations","compose","compose-hotswan","compose-ui","hot-reload","hotswan","jetpack","jetpack-compose","2026-06-12 02:00:09","\u003Ch1 align=\"center\">Jetpack Compose Animations\u003C\u002Fh1>\u003C\u002Fbr>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fopensource.org\u002Flicenses\u002FApache-2.0\">\u003Cimg alt=\"License\" src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-Apache%202.0-blue.svg\"\u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fandroid-arsenal.com\u002Fapi?level=23\">\u003Cimg alt=\"API\" src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAPI-23%2B-brightgreen.svg?style=flat\"\u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fskydoves\">\u003Cimg alt=\"Profile\" src=\"https:\u002F\u002Fskydoves.github.io\u002Fbadges\u002Fskydoves.svg\"\u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fdoveletter\">\u003Cimg alt=\"Profile\" src=\"https:\u002F\u002Fskydoves.github.io\u002Fbadges\u002Fdove-letter.svg\"\u002F>\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\nJetpack Compose animation playgrounds. Tweak literals at the top of any file, save, and watch the motion morph in front of you.\n\u003C\u002Fp>\n\n## Why this project\n\nThis project was built to tune and demonstrate Jetpack Compose animations on a real Android device, using [Compose HotSwan](https:\u002F\u002Fhotswan.dev\u002F) as the live editing loop. Animations are physical: a damping ratio of 0.6 versus 0.8, an easing of `FastOutSlowIn` versus `EaseOutBack`, a particle gravity of 1100 vs. 1800. None of those choices reads off the page. You feel them on the device, and the only way to find the right number is to keep changing it and looking at the result.\n\nEvery example here is a single composable file with its tunable values named as `val`s at the top of the function: durations, easings, stiffness, color palettes, particle counts. You change a number, save the file, and the running app picks up the new value within milliseconds, without rebuilding the project or losing your place in the navigation stack. The thinking behind this loop and how it changes the way you author animations is covered in [Compose Animation: Hot Reload](https:\u002F\u002Fhotswan.dev\u002Fblog\u002Fcompose-animation-hot-reload).\n\nYou can also run this app as a regular Compose project without Compose HotSwan, but the per parameter tuning loop is what the examples are designed around. In this repository, you'll find multiple self contained examples covering core animation APIs (`animate*AsState`, `AnimatedContent`, `AnimatedVisibility`, `Animatable`, `rememberInfiniteTransition`, `updateTransition`, `SharedTransitionLayout`), gesture driven motion, `Canvas` simulations, and physical effects.\n\n### Compose Hot Reload\n\nTo edit values and see changes live without rebuilding:\n\n1. Install the Compose HotSwan plugin following the [install guides](https:\u002F\u002Fhotswan.dev\u002Finstall), or expand the section below for the same steps inline.\n2. Run this project, and start Compose HotSwan.\n3. Open any animation example file and edit the constants near the top of the function.\n4. Save the file. Done. You will see the Compose UI is changing on a running Android app without re-compiling, re-installing, or re-navigating, just in ~100ms.\n\n\u003Cdetails>\n\u003Csummary>\u003Cstrong>Or follow the below instructions\u003C\u002Fstrong>\u003C\u002Fsummary>\n\n\u003Cbr\u002F>\n\n**1. Install the IDE Plugin**\n\nOpen your JetBrains IDE (Android Studio or IntelliJ IDEA), go to **Settings → Plugins → Marketplace**, and search for **\"Compose HotSwan\"**. Click Install and **restart the IDE**.\n\nYou can also install it directly from the [JetBrains Marketplace](https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F30551-compose-hotswan\u002F).\n\n![image](video\u002Fmarketplace.png)\n\n> **Kotlin Multiplatform?** If your project uses Kotlin Multiplatform, see the [Kotlin Multiplatform](https:\u002F\u002Fhotswan.dev\u002Fdocs\u002Fkotlin-multiplatform) guide for KMP specific setup and module configuration.\n\n**2. Configure Gradle**\n\nAdd the HotSwan compiler plugin to your project. Three files need to be updated.\n\n`libs.versions.toml`:\n\n```toml\n[plugins]\nhotswan-compiler = { id = \"com.github.skydoves.compose.hotswan.compiler\", version = \"1.3.0\" }\n```\n\nRoot `build.gradle.kts`:\n\n```kotlin\nalias(libs.plugins.hotswan.compiler) apply false\n```\n\nApp module `build.gradle.kts`:\n\n```kotlin\nalias(libs.plugins.hotswan.compiler)\n```\n\n> **IDE and Gradle versions must match.** The Gradle plugin version must match the IDE plugin version. When you update the IDE plugin, update the version in `libs.versions.toml` as well.\n\n**3. Build and Run Your App**\n\nBuild and run your app normally with the **Run** button. The Gradle plugin auto configures everything needed for hot reload in debug builds, no additional setup required.\n\n**4. Start HotSwan**\n\nOpen the HotSwan panel via **View → Tool Windows → HotSwan**. Select your target device and click **Start**. The status will change to **READY**.\n\n![image](video\u002Femulator-ready.png)\n\nOnce your app is running on the device, HotSwan connects automatically and the status changes to **WATCHING**.\n\n![image](video\u002Fwatching.png)\n\n**5. Start Hot Reloading**\n\nEdit any Kotlin file and save (`Cmd+S` \u002F `Ctrl+S`). HotSwan detects the change, compiles only the modified code, and applies the update to your running app. Your UI updates instantly without losing any state.\n\n\u003C\u002Fdetails>\n\nIf you skip step 1, the app still runs as a normal Compose app.\n\n### Compose Animations Article\n\nEvery animation here has a written walkthrough at [doveletter.dev\u002Fdocs\u002Fcompose-animations](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations). The page covers every entry in the gallery below, with the underlying APIs, the constants you can tune, and the reasoning behind each spec.\n\n## Animation Gallery\n\nEach example below is a single file. Open the source link to see the constants you can tweak.\n\n### 1. Animate Content Size\n\n\u003Cimg src=\"video\u002F1.gif\" width=\"100%\"\u002F>\n\nExpandable card that morphs height between two `Dp` values. Uses `animateDpAsState` with `tween` so the unfold timing reads as a single curve.\n\n- **Try tweaking:** `EXPAND_DURATION_MS`, `EXPAND_EASING`, `COLLAPSED_HEIGHT`, `EXPANDED_HEIGHT`.\n- **Source:** [`AnimationExample1.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample1.kt)\n- **Article:** [Animate Content Size](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fanimate-content-size). Demonstrates how `animateDpAsState` with a tween spec drives an expandable card's height transition, comparing `FastOutSlowInEasing` and `LinearEasing` to shape perceived motion between two fixed `Dp` endpoints.\n\n\n### 2. Animated Visibility\n\n\u003Cimg src=\"video\u002F2.gif\" width=\"100%\"\u002F>\n\nEnter and exit transitions composed from `slideIn`, `fadeIn`, `scaleIn`. A toggle flips the visibility, the spec defines the choreography.\n\n- **Try tweaking:** `ANIM_DURATION_MS`, `SLIDE_FROM_RIGHT`, the chosen `slideIn` \u002F `fadeIn` \u002F `scaleIn` combinators.\n- **Source:** [`AnimationExample2.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample2.kt)\n- **Article:** [Animated Visibility](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fanimated-visibility). Explores how the `+` operator composes `slideInHorizontally`, `fadeIn`, and `scaleIn` into parallel enter transitions inside `AnimatedVisibility`, with shared duration and direction giving synchronized choreography across multiple effects.\n\n\n### 3. Color State Morph\n\n\u003Cimg src=\"video\u002F3.gif\" width=\"100%\"\u002F>\n\n`animateColorAsState` walking through a palette of named theme colors. Pick a swatch, the background and accents follow.\n\n- **Try tweaking:** `COLOR_TRANSITION_MS`, the entries inside `PALETTE`.\n- **Source:** [`AnimationExample3.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample3.kt)\n- **Article:** [Color State Morph](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fcolor-state-morph). Uses `animateColorAsState` to interpolate between palette colors via color-space-aware conversion, with transitions triggered purely by state updates rather than explicit animation control.\n\n\n### 4. FAB Spring Morph\n\n\u003Cimg src=\"video\u002F4.gif\" width=\"100%\"\u002F>\n\nA floating action button that grows, rotates, and shifts color when toggled. Scale, corner radius, rotation, and color all run through `animateAsState` with `spring`.\n\n- **Try tweaking:** `springStiffness`, `springDampingRatio`, target sizes and corners.\n- **Source:** [`AnimationExample4.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample4.kt)\n- **Article:** [FAB Spring Morph](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Ffab-spring-morph). Applies spring physics with `Spring.StiffnessMediumLow` and `Spring.DampingRatioMediumBouncy` across four independent `animateAsState` channels, morphing a FAB's size, rotation, corner radius, and color in lockstep.\n\n\n### 5. Animated Counter\n\n\u003Cimg src=\"video\u002F5.gif\" width=\"100%\"\u002F>\n\nA number counter that slides and fades between values using `AnimatedContent`. The transition direction follows whether the count went up or down.\n\n- **Try tweaking:** `slideOffsetDivisor`, slide and fade durations, the `SizeTransform` easing.\n- **Source:** [`AnimationExample5.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample5.kt)\n- **Article:** [Animated Counter](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fanimated-counter). Reads direction from `targetState` and `initialState` inside `AnimatedContent`'s `transitionSpec`, composing `slideInVertically` and `fadeIn` per direction so digit swaps feel like climbing or falling.\n\n\n### 6. Crossfade Switcher\n\n\u003Cimg src=\"video\u002F6.gif\" width=\"100%\"\u002F>\n\n`Crossfade` between three selectable panels. The animation spec controls how snappy or lazy the swap feels.\n\n- **Try tweaking:** the `animationSpec` passed to `Crossfade`, the panel content.\n- **Source:** [`AnimationExample6.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample6.kt)\n- **Article:** [Crossfade Switcher](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fcrossfade-switcher). Treats `Crossfade` as the simplest opacity-only content swap and shows how a single `animationSpec` argument controls the entire perceptual weight of the swap without geometric complications.\n\n\n### 7. Pulsing Heart\n\n\u003Cimg src=\"video\u002F7.gif\" width=\"100%\"\u002F>\n\n`rememberInfiniteTransition` driving scale and alpha at the same time. The result is a soft heartbeat with a bright on, dim off rhythm.\n\n- **Try tweaking:** `PULSE_MIN_SCALE`, `PULSE_MAX_SCALE`, `PULSE_DURATION_MS`, `RepeatMode`.\n- **Source:** [`AnimationExample7.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample7.kt)\n- **Article:** [Pulsing Heart](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fpulsing-heart). Builds synchronized infinite motion through `rememberInfiniteTransition` and `animateFloat` calls with `RepeatMode.Reverse`, letting two properties (scale and alpha) pulse in lockstep without any state changes.\n\n\n### 8. Custom Loading Spinner\n\n\u003Cimg src=\"video\u002F8.gif\" width=\"100%\"\u002F>\n\nA loading indicator built from infinite rotation plus a color sweep. Shows how to layer two infinite transitions on the same `graphicsLayer`.\n\n- **Try tweaking:** rotation duration, color list, sweep keyframes.\n- **Source:** [`AnimationExample8.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample8.kt)\n- **Article:** [Custom Loading Spinner](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fcustom-loading-spinner). Composes two infinite animations (rotation and color sweep) on a single `rememberInfiniteTransition` with intentionally mismatched durations to prevent visual repetition while keeping the cost in the draw phase.\n\n\n### 9. Spring Drag Box\n\n\u003Cimg src=\"video\u002F9.gif\" width=\"100%\"\u002F>\n\nA box you can drag with `pointerInput`, then release to spring back to origin via `Animatable.animateTo`. Tuning stiffness flips the feel between snap and wobble.\n\n- **Try tweaking:** `SPRING_STIFFNESS`, `SPRING_DAMPING`, the target position on release.\n- **Source:** [`AnimationExample9.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample9.kt)\n- **Article:** [Spring Drag Box](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fspring-drag-box). Pairs `Animatable.snapTo` for one-to-one gesture tracking with `animateTo` using spring physics for the release rebound, letting the same state holder bridge manual writes and physics-driven motion.\n\n\n### 10. Easing Showcase\n\n\u003Cimg src=\"video\u002F10.gif\" width=\"100%\"\u002F>\n\nSix runners race side by side, each using a different `Easing`. The strip makes the difference between linear, ease in, ease out, fast out slow in, anticipate, overshoot visible at a glance.\n\n- **Try tweaking:** swap any `Easing` function in the entries list, change `RACE_DURATION_MS`.\n- **Source:** [`AnimationExample10.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample10.kt)\n- **Article:** [Easing Showcase](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Feasing-showcase). Races six `animateFloatAsState` animations with identical targets but different `Easing` curves (`LinearEasing`, `FastOutSlowInEasing`, `CubicBezierEasing`) to isolate how easing defines perceived motion character independent of duration.\n\n\n### 11. Play \u002F Pause Morph\n\n\u003Cimg src=\"video\u002F11.gif\" width=\"100%\"\u002F>\n\nA play triangle that morphs into a pause pair through `Path` interpolation on a `Canvas`. The shape itself is the animation, no sprite swap.\n\n- **Try tweaking:** `MORPH_DURATION_MS`, the source and target path coordinates, fill colors.\n- **Source:** [`AnimationExample11.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample11.kt)\n- **Article:** [Play \u002F Pause Morph](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fplay-pause-morph). Treats icon morphing as geometry interpolation using `Canvas` and per-vertex `lerp` on matched point lists, driving both the shape and the background color from a single `animateFloatAsState` fraction.\n\n\n### 12. Shared Bounds Expansion\n\n\u003Cimg src=\"video\u002F12.gif\" width=\"100%\"\u002F>\n\nTap a card and watch it expand into a detail view through `SharedTransitionLayout`. Matching keys on the source and destination tie their bounds together.\n\n- **Try tweaking:** `BOUNDS_DURATION_MS`, `BOUNDS_EASING`, `DETAIL_HEIGHT_DP`, the card list.\n- **Source:** [`AnimationExample12.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample12.kt)\n- **Article:** [Shared Bounds Expansion](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fshared-bounds-expansion). Uses `SharedTransitionLayout` with `rememberSharedContentState` to correlate source and destination cards by key, then lets `BoundsTransform` interpolate the rectangles between list and detail states with synchronized timing.\n\n\n### 13. Swipeable Cards\n\n\u003Cimg src=\"video\u002F13.gif\" width=\"100%\"\u002F>\n\nA Tinder style card stack. Drag past the threshold and the card flings off, tilted by a rotation factor proportional to the offset.\n\n- **Try tweaking:** `SWIPE_THRESHOLD_FRACTION`, `ROTATION_FACTOR`, `FLING_STIFFNESS`, `FLING_DURATION_MS`.\n- **Source:** [`AnimationExample13.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample13.kt)\n- **Article:** [Swipeable Cards](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fswipeable-cards). Combines `Animatable.snapTo` during drag for one-to-one pointer tracking with `animateTo` using spring or tween on release, coupling rotation as a `graphicsLayer` function of the same offset for visual coherence.\n\n\n### 14. Radial FAB Menu\n\n\u003Cimg src=\"video\u002F14.gif\" width=\"100%\"\u002F>\n\nA floating action button that explodes into satellite buttons along an arc. Each satellite has its own `Animatable`, animated through a spring with a per index stagger delay so the menu unfurls and refolds.\n\n- **Try tweaking:** `ITEM_COUNT`, `RADIUS_DP`, `STAGGER_MS`, `SPRING_STIFFNESS`, `SPRING_DAMPING`, `ARC_DEG`.\n- **Source:** [`AnimationExample14.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample14.kt)\n- **Article:** [Radial FAB Menu](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fradial-fab-menu). Distributes satellites along a polar coordinate arc using `cos` and `sin`, with per-item `Animatable` instances staggered through `LaunchedEffect` delays so the menu unfurls and refolds symmetrically.\n\n\n### 15. 3D Card Flip\n\n\u003Cimg src=\"video\u002F15.gif\" width=\"100%\"\u002F>\n\nA card that flips in 3D using `graphicsLayer.rotationY` with a tuned `cameraDistance`. The front and back swap content at 90 degrees.\n\n- **Try tweaking:** `FLIP_DURATION_MS`, `CAMERA_DISTANCE`, the front and back colors.\n- **Source:** [`AnimationExample15.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample15.kt)\n- **Article:** [3D Card Flip](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fcard-flip-3d). Applies `rotationY` on `graphicsLayer` with `cameraDistance` scaled by density to create perspective projection, swapping content at 90 degrees when the layer becomes edge on.\n\n\n### 16. Confetti Burst\n\n\u003Cimg src=\"video\u002F16.gif\" width=\"100%\"\u002F>\n\nTap anywhere in the canvas and a one shot burst of rotating paper rectangles erupts from that point. Each piece carries its own velocity, rotation speed, lateral wobble, lifetime, and color. Multiple bursts stack on top of each other.\n\n- **Try tweaking:** `BURST_COUNT`, `GRAVITY`, `SPEED_MIN\u002FMAX`, `SPREAD_DEG`, `LAUNCH_ANGLE_DEG`, `AIR_DRAG`, `WOBBLE_AMP`, `ROT_SPEED_MAX`, `PALETTE`.\n- **Source:** [`AnimationExample16.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample16.kt)\n- **Article:** [Confetti Burst](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fconfetti-burst). Models particles as mutable class instances updated in a `withFrameNanos` loop, integrating gravity and exponential drag frame-rate independently while `Canvas` renders all pieces in a single pass with per-particle alpha fade.\n\n\n### 17. Wave Field\n\n\u003Cimg src=\"video\u002F17.gif\" width=\"100%\"\u002F>\n\nMultiple sine wave layers stacked for parallax, each driven by its own phase, frequency, and amplitude ramps. Looks like a calm sea or a storm depending on the constants.\n\n- **Try tweaking:** `BASE_AMPLITUDE_DP`, `BASE_PHASE_SPEED`, `FREQ_RAMP`, `AMPL_FALLOFF`, `LAYER_COUNT`.\n- **Source:** [`AnimationExample17.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample17.kt)\n- **Article:** [Wave Field](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fwave-field). Stacks multiple sine wave layers with per-layer ramps for frequency, amplitude, and phase speed to create parallax depth, with `withFrameNanos` driving time and a `waveY` helper sampling positions into a `Path`.\n\n\n### 18. Metaball Liquid\n\n\u003Cimg src=\"video\u002F18.gif\" width=\"100%\"\u002F>\n\nDrifting blobs that fuse into a single liquid mass when they overlap. The fusion comes from additive blend on stacked radial gradients.\n\n- **Try tweaking:** `ballCount`, `ballRadiusMin\u002FMaxDp`, `glowRadiusMult`, `maxSpeedDpPerSec`, `driftNoise`.\n- **Source:** [`AnimationExample18.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample18.kt)\n- **Article:** [Metaball Liquid](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fmetaball-liquid). Blends drifting balls using `Brush.radialGradient` with `BlendMode.Plus` on an offscreen `graphicsLayer`, so overlapping alpha values create the illusion of a fused liquid mass.\n\n\n### 19. Mesh Aurora\n\n\u003Cimg src=\"video\u002F19.gif\" width=\"100%\"\u002F>\n\nColor orbs orbit on elliptical paths, additive blended into a living mesh gradient. Hue rotation cycles the entire palette over time.\n\n- **Try tweaking:** `ORB_COUNT`, `ORB_GLOW_RADIUS_DP`, `ORBIT_RADIUS_MIN\u002FMAX_DP`, `HUE_ROTATION_SPEED`, `PALETTE`.\n- **Source:** [`AnimationExample19.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample19.kt)\n- **Article:** [Mesh Aurora](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fmesh-aurora). Composes orbiting color orbs along elliptical parametric paths while HSV hue rotation cycles each palette entry independently, with additive blending on an offscreen layer producing a living gradient mesh.\n\n\n### 20. Pendulum Wave\n\n\u003Cimg src=\"video\u002F20.gif\" width=\"100%\"\u002F>\n\nN pendulums with progressively shorter periods. They start in phase, drift apart into apparent chaos, and resync at the period boundary.\n\n- **Try tweaking:** `PENDULUM_COUNT`, `BASE_PERIOD_SEC`, `SYNC_PERIOD_SEC`, the bob colors.\n- **Source:** [`AnimationExample20.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample20.kt)\n- **Article:** [Pendulum Wave](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Fpendulum-wave). Computes each pendulum's angle as `cos(omega * time)` with periods chosen so all pendulums resync at a fixed `SYNC_PERIOD_SEC` boundary, creating traveling waves and apparent chaos that cycle predictably.\n\n\n### 21. Rainy\n\n\u003Cimg src=\"video\u002F21.gif\" width=\"100%\"\u002F>\n\nContinuous rain streaks falling at an angle, with depth based parallax and optional ground splash marks.\n\n- **Try tweaking:** `DROP_COUNT`, `ANGLE_DEG`, `SPEED_MIN\u002FMAX_DP_PER_SEC`, `STREAK_LENGTH`, `SPLASH_ENABLED`.\n- **Source:** [`AnimationExample21.kt`](app\u002Fsrc\u002Fmain\u002Fkotlin\u002Fcom\u002Fskydoves\u002Fhotreloadanimations\u002Fanimations\u002FAnimationExample21.kt)\n- **Article:** [Rainy](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations\u002Frainy). Recycles a fixed pool of `Drop` objects advanced by `velocity * dt`, with per-drop speed encoding depth parallax, direction taken from `cos`\u002F`sin` of a single `ANGLE_DEG`, and optional splash circles marking ground contact.\n\n\n## [Tuning Compose Animations Without Rebuilding: Hot Reload for Dynamic Design](https:\u002F\u002Fhotswan.dev\u002Fblog\u002Fcompose-animation-hot-reload)\n\n![image](video\u002Fcover.png)\n\nWith Compose hot reload, you change the value, save, and the animation plays with the new value on your running device in under a second. No rebuild. No restart. No navigating back. You stay on the exact screen, the exact state, and see the exact difference between the old value and the new one. This turns animation tuning from a guessing game into a visual, iterative process.\n\n[In this article](https:\u002F\u002Fhotswan.dev\u002Fblog\u002Fcompose-animation-hot-reload), you will explore four real world examples of animation development with hot reload: content size transitions, grid item animations, custom wave motion, and animation spec tuning.\n\n## [Articles for Jetpack Compose Animation](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations)\n\n![image](video\u002Fcompose-animations-hub.png)\n\nEach entry in the gallery above has a focused walkthrough on the [Compose Animations hub](https:\u002F\u002Fdoveletter.dev\u002Fdocs\u002Fcompose-animations). The page collects every animation as a self contained card with the title, a one line description, and a preview of the source, so you can scan the catalog and jump straight into whichever motion you want to read about.\n\nInside each article the full composable file is annotated section by section: which constants drive the timing, why a given `spring` or `tween` was chosen, what the geometry is doing on the `Canvas`, and how to twist the same code into a different shape. Use the gallery here to browse, and the hub to read end to end.\n\n## Find this project useful? :heart:\n\nSupport it by joining [stargazers](https:\u002F\u002Fgithub.com\u002Fskydoves\u002Fcompose-animations\u002Fstargazers) for this repository. :star: \u003Cbr>\nAlso, [follow me](https:\u002F\u002Fgithub.com\u002Fskydoves) on GitHub for my next creations.\n\n# License\n\n```xml\nDesigned and developed by 2026 skydoves (Jaewoong Eum)\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","Jetpack Compose Animations 是一个专为 Jetpack Compose 设计的动画集合，旨在展示最佳实践。项目提供了多种动画效果，包括`animate*AsState`、`AnimatedContent`、`Animatable`等核心API，并支持手势驱动动画及物理效果模拟。利用Compose HotSwan插件，开发者可以在不重新编译的情况下实时调整动画参数（如持续时间、缓动函数等），并即时查看变化结果，极大地提高了动画调优效率。该工具非常适合Android应用开发中需要精细控制UI动画效果的场景。",2,"2026-06-11 02:31:06","CREATED_QUERY"]