Actor class

A widget that applies one or more animation Acts to its child.

Overview

Actor is the core visual building block for Cue animations. It wraps a child widget with a list of acts — declarative descriptions of how the widget should look at different points in the animation.

Actor is passive. It does not trigger or control animations on its own. All animation progress is driven externally by the nearest ancestor Cue widget, which exposes a CueScope via InheritedWidget. Actor reads that scope and reacts to it. Without an ancestor Cue, an Actor has no effect.

The typical pattern is:

Cue.onToggle(
  toggled: isExpanded,
  motion: .smooth(),
  child: Actor(
    acts: [.fadeIn(), .slideUp()],
    child: MyWidget(),
  ),
)

Motion

Motion controls the timing and easing of all acts within this Actor. The resolution order is:

  1. If an individual act specifies its own motion, that is used for that act including both forward and reverse motion unless specified.
  2. Otherwise, the Actor's motion is used as the default for all acts.
  3. If motion is null, the Actor inherits from the parent Cue widget. -> timeline.defaultConfig

Reverse motion follows the same rule independently. If reverseMotion is not provided, motion doubles as the reverse motion too. Reverse motion is NOT inherited from the parent Cue widget when motion is explicitly set — motion is used for both directions unless reverseMotion is explicitly specified.

// motion: CueMotion.smooth() applies to both forward and reverse
Actor(
  motion: .smooth(),
  acts: [.fadeIn(), .slideUp()],
  child: MyWidget(),
)

// Different timing for forward and reverse
Actor(
  motion: .smooth(),
  reverseMotion: .linear(200.ms),
  acts: [.fadeIn(), .slideUp()],
  child: MyWidget(),
)

// An individual act can override the Actor's motion
Actor(
  motion: .smooth(),           // default for all acts
  acts: [
    .fadeIn(),                               // uses .smooth() for both directions
    .scale(to: 1.1, motion: .bouncy()),      // overrides with its own motion
  ],
  child: MyWidget(),
)

Default from values

Most acts have sensible identity defaults for from, so you rarely need to specify it explicitly:

  • Transform acts (.scale, .rotate, .translate, etc.) default to identity (no transform)
  • .opacity defaults to from: 1.0; .fadeIn() defaults to from: 0.0
  • .blur defaults to from: 0.0

When no meaningful identity exists, from is required by the act's constructor.

Rules

Only one Act of each type (key) may be used per Actor. Using two Acts with the same key throws a StateError at runtime. Note that some seemingly different acts share a key — all slide variants (.slide(), .slideX(), .slideY(), .slideUp(), etc.) share the same key and cannot be combined:

// Not allowed — duplicate ScaleAct
Actor(acts: [.scale(to: 1.2), .scale(to: 0.8)], child: widget)

// Not allowed — slideUp and slideY share the same key
Actor(acts: [.slideUp(), .slideY(from: -0.5)], child: widget)

Shorthand factory constructors

Acts can be created via shorthand Act. factories or direct class constructors:

Actor(
  acts: [
    .scale(from: 0.8),  // to: 1.0 is default
    .fadeIn(),
    .slideUp(),
    .blur(from: 8),     // to: 0.0 is default
  ],
  child: MyWidget(),
)

Keyframe animations

Acts support keyframed sequences via Keyframes or Keyframes.fractional. Use the .key() shorthand constructor for a more readable syntax. Each key represents a target value to animate towards, not a starting point.

// Motion-based keyframes — motion is required at the Keyframes level;
// per-frame motion is an optional override.
Actor(
  acts: [
    TranslateAct.keyframed(
      frames: Keyframes([
        .key(Offset(100, 0)),                    // uses Keyframes-level motion
        .key(Offset.zero, motion: .bouncy()),    // per-frame override
      ], motion: .smooth()),
    ),
  ],
  child: MyWidget(),
)

For acts with no implicit starting value (e.g. SizedBoxAct), the first key defines the initial value — it is not animated to; it is the starting point. Any motion on the first key is ignored:

Actor(
  acts: [
    SizedBoxAct.keyframed(
      frames: Keyframes([
        .key(Size(80, 80)),     // initial value, not animated to
        .key(Size(200, 80)),
        .key(Size(80, 80)),
      ], motion: .smooth()),
    ),
  ],
  child: MyWidget(),
)
// Fractional keyframes — frames positioned at fractions of the total duration.
// An optional curve can be set at the Keyframes level (applies to all frames)
// or at the individual key level (overrides the Keyframes-level curve for that frame).
Actor(
  acts: [
    TranslateAct.keyframed(
      frames: Keyframes.fractional([
        .key(Offset(100, 0), at: 0.5),
        .key(Offset.zero, at: 1.0, curve: Curves.easeOut),  // per-frame override
      ], curve: Curves.easeIn),  // default curve for all frames
    ),
  ],
  child: MyWidget(),
)

Delays

delay and reverseDelay set a base time offset for this Actor. Any delay on an individual act is added on top of the Actor's delay:

// Actor delay: 100ms, act delay: 200ms → act plays after 300ms total
Actor(
  delay: 100.ms,
  acts: [
    .fadeIn(delay: 200.ms),   // plays after 300ms
    .slideUp(),               // plays after 100ms (Actor delay only)
  ],
  child: Item(),
)

Animation cache

Actor maintains an internal cache of built animations keyed by ActKey. Animations are only rebuilt when the corresponding act or its configuration actually changes — if an act is identical to its previous value, the cached animation is reused. Acts removed from the list have their animations released immediately.

When fromCurrentValue: true is set on Cue.onChange, Actor captures the current animated value of each act just before a re-animation begins and passes it as the implicit from to the new animation. This ensures smooth transitions when acts change mid-flight without a visible jump.

Inheritance
Available extensions

Constructors

Actor({Key? key, required List<Act> acts, required Widget child, CueMotion? motion, CueMotion? reverseMotion, Duration delay = Duration.zero, Duration reverseDelay = Duration.zero, bool addRepaintBoundary = false})
Default constructor.
const

Properties

acts → List<Act>
The list of animation acts to apply to child.
final
addRepaintBoundary → bool
Wraps the animated widget in a RepaintBoundary.
final
child → Widget
The widget to animate.
final
delay → Duration
Delay before the forward animation starts.
final
hashCode → int
The hash code for this object.
no setterinherited
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
motion → CueMotion?
Optional motion override for all acts in this Actor. When null, inherits the parent Cue widget's motion.
final
reverseDelay → Duration
Delay before the reverse animation starts.
final
reverseMotion → CueMotion?
Optional motion override for the reverse pass. When null, falls back to motion, then to the parent's reverse motion.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited

Methods

act(List<Act> acts, {CueMotion? motion, CueMotion? reverseMotion, Duration delay = Duration.zero, Duration reverseDelay = Duration.zero}) → Widget

Available on Widget, provided by the ActorExtenstion extension

Wraps this widget with an Actor using the provided acts.
createElement() → StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() → State<Actor>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited