Skip to content

Add support for animated effects on spans of text#56702

Closed
andrewdacenko wants to merge 2 commits intofacebook:mainfrom
andrewdacenko:export-D97399151
Closed

Add support for animated effects on spans of text#56702
andrewdacenko wants to merge 2 commits intofacebook:mainfrom
andrewdacenko:export-D97399151

Conversation

@andrewdacenko
Copy link
Copy Markdown
Contributor

Summary:
Adds AnimatedEffectSpan, a new span type for animated effects drawn on top
of text in PreparedLayoutTextView. Unlike DrawCommandSpan which provides
static onPreDraw/onDraw hooks, AnimatedEffectSpan supports animation via
a requestAnimationFrame-style API where the span receives a time delta each
frame and returns whether it wants another frame.

Key design decisions:

  • Independent from DrawCommandSpan — does not subclass it
  • Does not implement UpdateAppearance — animated effects don't affect text measurement or paint state
  • Implements ReactSpan for integration with RN's span management
  • Annotated UnstableReactNativeAPI — callers must opt in
  • Zero overhead for non-animated text: delta computation and frame scheduling only happen when animated spans exist
  • Frame timing resets on visibility changes and view recycling to prevent delta spikes

Changelog: [Internal]

Reviewed By: alanleedev

Differential Revision: D97399151

… isolation (facebook#56688)

Summary:

`PreparedLayoutTextView` can receive shared `PreparedLayout` instances
from a C++ LRU cache. Multiple views rendering identical text share the
same `Layout` → `Spannable` → span objects. Stateless spans are fine to
share, but stateful spans like `SpoilerEffectSpan` (particles, dismiss
state) would have one view's tap-dismiss corrupt all other views sharing
that layout.

Introduces a `StatefulSpan` marker interface whose presence tells
`PreparedLayoutTextView` to clone the spannable with fresh span instances.
The Layout is reused via a delegating subclass (`MutableSpannableLayout`)
that passes the cloned Spannable to `Layout`'s protected constructor and
delegates all line metrics to the original. The mutable Spannable can be
useful for spans which affect display, but do not alter existing layout
calculations. No StaticLayout rebuild needed.

Performance: Only views with stateful spans pay the cost. `getSpans()` is
O(spans), `SpannableString` copy is O(text+spans). Views without
`StatefulSpan` are completely unchanged.

Changelog: [internal]

Reviewed By: alanleedev

Differential Revision: D97415850
Summary:
Adds `AnimatedEffectSpan`, a new span type for animated effects drawn on top
of text in `PreparedLayoutTextView`. Unlike `DrawCommandSpan` which provides
static `onPreDraw`/`onDraw` hooks, `AnimatedEffectSpan` supports animation via
a `requestAnimationFrame`-style API where the span receives a time delta each
frame and returns whether it wants another frame.

Key design decisions:
- Independent from `DrawCommandSpan` — does not subclass it
- Does not implement `UpdateAppearance` — animated effects don't affect text measurement or paint state
- Implements `ReactSpan` for integration with RN's span management
- Annotated `UnstableReactNativeAPI` — callers must opt in
- Zero overhead for non-animated text: delta computation and frame scheduling only happen when animated spans exist
- Frame timing resets on visibility changes and view recycling to prevent delta spikes

Changelog: [Internal]

Reviewed By: alanleedev

Differential Revision: D97399151
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 6, 2026
@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 6, 2026

@andrewdacenko has exported this pull request. If you are a Meta employee, you can view the originating Diff in D97399151.

@facebook-github-tools facebook-github-tools Bot added p: Facebook Partner: Facebook Partner labels May 6, 2026
@meta-codesync meta-codesync Bot closed this in 71a0d5d May 6, 2026
@facebook-github-tools facebook-github-tools Bot added the Merged This PR has been merged. label May 6, 2026
@react-native-bot
Copy link
Copy Markdown
Collaborator

This pull request was successfully merged by @andrewdacenko in 71a0d5d

When will my fix make it into a release? | How to file a pick request?

@meta-codesync
Copy link
Copy Markdown

meta-codesync Bot commented May 6, 2026

This pull request has been merged in 71a0d5d.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged This PR has been merged. meta-exported p: Facebook Partner: Facebook Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants