GlassMorphController class

A Flutter-idiomatic controller for liquid glass morph animations.

Works like AnimationController but encapsulates the iOS 26 spring physics, J-curve interpolation, and LiquidMorphState computation behind a clean, semantic API.

Lifecycle

GlassMorphController must be created inside a State that mixes in TickerProviderStateMixin and disposed in State.dispose.

class _MyWidgetState extends State<MyWidget> with TickerProviderStateMixin {
  late final GlassMorphController _morph;

  @override
  void initState() {
    super.initState();
    _morph = GlassMorphController(vsync: this);
    _morph.addListener(_onFrame);
  }

  @override
  void dispose() {
    _morph.dispose();
    super.dispose();
  }

  void _open()  => _morph.open();
  void _close() => _morph.close();

  void _onFrame() {
    if (!mounted) return;
    setState(() {});
  }
}

Computing render state

final state = _morph.computeState(
  finalDx: finalDx,
  finalDy: finalDy,
  horizontalOffset: _horizontalOffset,
  verticalOffset: _verticalOffset,
);

// Use state.pathT, state.anchorScale, state.blend, etc. in your layout.

Customisation

Use speed and style for safe, semantic control. Avoid constructing LiquidMorphPhysics manually with custom spring constants — the physics parameters are interdependent and incorrect values produce unstable animations.

Inheritance

Constructors

GlassMorphController({required TickerProvider vsync, MorphSpeed speed = MorphSpeed.normal, MorphStyle style = MorphStyle.teardrop})
Creates a GlassMorphController.

Properties

animation → AnimationController
The underlying AnimationController for callers that need to listen to AnimationStatus changes or drive additional Animations from it.
no setter
disableAnimations → bool
Whether reduced-motion override is currently active.
no setter
hasHandedOff → bool
Whether the anchor blob has handed off back to the real trigger.
no setter
hashCode → int
The hash code for this object.
no setterinherited
hasListeners → bool
Whether any listeners are currently registered.
no setterinherited
isClosing → bool
Whether the controller is in the closing phase.
no setter
isShowing → bool
Whether the morph overlay should currently be visible.
no setter
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
speed → MorphSpeed
Speed profile for the morph animation.
final
status → AnimationStatus
Current AnimationStatus of the underlying controller.
no setter
style → MorphStyle
Visual shape style of the morph transition.
final
value → double
The raw, unclamped spring simulation value.
no setter
velocity → double
Instantaneous velocity of the spring simulation.
no setter

Methods

addListener(VoidCallback listener) → void
Register a closure to be called when the object changes.
inherited
close() → void
Closes the morph animation with the iOS 26 rubber-band bounce.
computeState({required double finalDx, required double finalDy, double horizontalOffset = 0.0, double verticalOffset = 0.0}) → LiquidMorphState
Computes the current LiquidMorphState for the given layout geometry.
dispose() → void
Discards any resources used by the object.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
notifyListeners() → void
Call all the registered listeners.
inherited
open() → void
Opens the morph animation from the current position.
removeListener(VoidCallback listener) → void
Remove a previously registered closure from the list of closures that are notified when the object changes.
inherited
reset() → void
Immediately resets the controller to its resting closed state (value = 0.0, velocity = 0.0) without running an animation.
setDisableAnimations(bool disableAnimations) → void
Updates the reduced-motion override.
toString() → String
A string representation of this object.
inherited

Operators

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