Generic native layout-animation backend (Core Animation + Android animators)#9647
Draft
piaskowyk wants to merge 1 commit into
Draft
Conversation
Replace the C++ per-preset computation with a generic JS-sampled keyframe descriptor played by the platform animation engine (Core Animation on iOS, android.animation on Android). The sampler ticks the existing Reanimated animation objects, so all presets, sequences, easings and springs are supported automatically. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR builds on the Core Animation layout-animations PoC (#8442) and turns it into a complete, cross-platform native backend for entering / exiting / layout animations. When enabled, layout animations bypass the per-frame React/JS mutation path entirely and are played by the platform's native animation engine — Core Animation on iOS and
android.animationon Android — for better performance.It targets
@pawicao/core-animation-layout-animationsand is intended to be merged into that branch.Approach — one generic, JS-sampled keyframe descriptor
The PoC re-implemented each preset's math in C++ (
NativeLayoutAnimationPreset*) and only animatedposition.x/y. That doesn't scale to the ~90 presets (sequences, easings, springs, opacity/scale/rotation/skew/perspective…).Instead, this PR samples the existing Reanimated animation objects — the very same
withTiming/withSequence/withSpring/ easing the legacy path drives — across virtual time into one generic, platform-agnostic keyframe descriptor:Because we tick the real animation objects (on the UI runtime, where
defineAnimationresolves to concrete objects), every preset is supported automatically, with easing and spring physics baked into the sampled curve. Channels are canonical:opacity,originX/Y,width/height,translateX/Y,scaleX/Y,rotation,rotationX/Y,skewX,perspective.Flow: native proxy (flag on) → C++
LayoutAnimationsManager::startNativeLayoutAnimationcalls JSLayoutAnimationsManager.computeNativeDescriptor(type, values, config)→ parses the descriptor → hands it to the platform player viaPlatformDepMethodsHolder.runNativeLayoutAnimation. Completion runs through the existingendLayoutAnimationpath (so exiting views are still removed correctly).What's new
Shared (TS):
layoutReanimation/nativeAnimationDescriptor.ts— the generic sampler + descriptor types.animationsManager.ts—computeNativeDescriptoron the UI-runtime manager.IOS_USE_NATIVE_LAYOUT_ANIMATIONS, addedANDROID_USE_NATIVE_LAYOUT_ANIMATIONS.Shared (C++):
NativeLayoutAnimationDescriptor.h— the descriptor struct.LayoutAnimationsManager/LayoutAnimationsProxy_Legacy/ReanimatedModuleProxyrewired to compute the descriptor in JS and call a cross-platformRunNativeLayoutAnimationplayer.NativeLayoutAnimation*,NativeLayoutAnimationPreset*Factory/Impl).iOS:
REANodesManager runNativeLayoutAnimationForView:— generic Core Animation player:CAKeyframeAnimations for opacity / composedCATransform3D/position/bounds.size, committing final values to the model layer undersetDisableActions:YES(no snap-back), and using the presentation layer for seamless interruption.Android (new native backend):
LayoutAnimationCallback(C++ HybridClass + Kotlin) bridges completion back to C++.NativeProxy::runNativeLayoutAnimationflattens the descriptor over JNI.NativeLayoutAnimator.ktreplays it on theViewviaValueAnimator(alpha / translation / scale / rotation / cameraDistance), driven linearly since easing/springs are pre-baked.Known limitations / follow-ups
Viewskew, soLightSpeed*loses its shear;width/heightare approximated as a top-left scale (no child relayout mid-animation).rawConfig/applyRawConfigplumbing is now vestigial (the descriptor is derived from the serialized builder) and can be removed in a follow-up.Test plan
fabric-exampleapp.*_USE_NATIVE_LAYOUT_ANIMATIONSflag and exercise the layout-animation examples (entering/exiting/linear-transition, interrupted animations)