Claude
Skills
Sign in
Back

custom-plugin-flutter-skill-animations

Included with Lifetime
$97 forever

Production-grade Flutter animations mastery - Implicit and explicit animations, AnimationController, Hero transitions, physics-based motion, Lottie/Rive integration, 60fps optimization with comprehensive code examples

Generalscriptsassets

What this skill does


# custom-plugin-flutter: Animations Skill

## Quick Start - Production Animation Pattern

```dart
class AnimatedProductCard extends StatefulWidget {
  final Product product;
  final bool isSelected;

  const AnimatedProductCard({
    required this.product,
    required this.isSelected,
  });

  @override
  State<AnimatedProductCard> createState() => _AnimatedProductCardState();
}

class _AnimatedProductCardState extends State<AnimatedProductCard>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  late final Animation<double> _scaleAnimation;
  late final Animation<double> _opacityAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 200),
      vsync: this,
    );

    _scaleAnimation = Tween<double>(begin: 1.0, end: 0.95).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );

    _opacityAnimation = Tween<double>(begin: 1.0, end: 0.8).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
  }

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

  void _onTapDown(TapDownDetails details) => _controller.forward();
  void _onTapUp(TapUpDetails details) => _controller.reverse();
  void _onTapCancel() => _controller.reverse();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: _onTapDown,
      onTapUp: _onTapUp,
      onTapCancel: _onTapCancel,
      child: AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
          return Transform.scale(
            scale: _scaleAnimation.value,
            child: Opacity(
              opacity: _opacityAnimation.value,
              child: child,
            ),
          );
        },
        child: AnimatedContainer(
          duration: const Duration(milliseconds: 300),
          decoration: BoxDecoration(
            border: Border.all(
              color: widget.isSelected ? Colors.blue : Colors.grey,
              width: widget.isSelected ? 2 : 1,
            ),
            borderRadius: BorderRadius.circular(12),
          ),
          child: ProductContent(product: widget.product),
        ),
      ),
    );
  }
}
```

## 1. Implicit Animations

### Built-in Animated Widgets

```dart
// AnimatedContainer - Animate multiple properties
AnimatedContainer(
  duration: Duration(milliseconds: 300),
  curve: Curves.easeInOut,
  width: isExpanded ? 300 : 100,
  height: isExpanded ? 200 : 100,
  decoration: BoxDecoration(
    color: isActive ? Colors.blue : Colors.grey,
    borderRadius: BorderRadius.circular(isExpanded ? 16 : 8),
    boxShadow: isActive ? [BoxShadow(blurRadius: 10)] : [],
  ),
  child: content,
)

// AnimatedOpacity
AnimatedOpacity(
  opacity: isVisible ? 1.0 : 0.0,
  duration: Duration(milliseconds: 200),
  child: content,
)

// AnimatedPositioned (inside Stack)
AnimatedPositioned(
  duration: Duration(milliseconds: 300),
  left: isLeft ? 0 : 100,
  top: isTop ? 0 : 100,
  child: widget,
)

// AnimatedSwitcher - Cross-fade between widgets
AnimatedSwitcher(
  duration: Duration(milliseconds: 300),
  transitionBuilder: (child, animation) {
    return FadeTransition(opacity: animation, child: child);
  },
  child: Text(
    currentText,
    key: ValueKey(currentText), // Important!
  ),
)

// TweenAnimationBuilder - Custom implicit animation
TweenAnimationBuilder<double>(
  tween: Tween(begin: 0, end: progress),
  duration: Duration(milliseconds: 500),
  builder: (context, value, child) {
    return CircularProgressIndicator(value: value);
  },
)
```

## 2. Explicit Animations

### AnimationController Pattern

```dart
class ExplicitAnimationWidget extends StatefulWidget {
  @override
  State<ExplicitAnimationWidget> createState() => _ExplicitAnimationWidgetState();
}

class _ExplicitAnimationWidgetState extends State<ExplicitAnimationWidget>
    with TickerProviderStateMixin {
  late final AnimationController _controller;
  late final Animation<Offset> _slideAnimation;
  late final Animation<double> _fadeAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(milliseconds: 500),
      vsync: this,
    );

    _slideAnimation = Tween<Offset>(
      begin: Offset(0, 1),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Interval(0.0, 0.6, curve: Curves.easeOut),
    ));

    _fadeAnimation = Tween<double>(
      begin: 0,
      end: 1,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Interval(0.3, 1.0, curve: Curves.easeIn),
    ));

    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _slideAnimation,
      child: FadeTransition(
        opacity: _fadeAnimation,
        child: Content(),
      ),
    );
  }
}
```

### Animation Transitions

```dart
// Built-in transitions
FadeTransition(opacity: animation, child: widget)
SlideTransition(position: offsetAnimation, child: widget)
ScaleTransition(scale: animation, child: widget)
RotationTransition(turns: animation, child: widget)
SizeTransition(sizeFactor: animation, child: widget)

// AnimatedBuilder - Custom rendering
AnimatedBuilder(
  animation: _controller,
  builder: (context, child) {
    return Transform(
      transform: Matrix4.identity()
        ..setEntry(3, 2, 0.001)
        ..rotateY(_controller.value * pi),
      alignment: Alignment.center,
      child: child,
    );
  },
  child: Card(),
)
```

## 3. Hero Animations

```dart
// Source screen
Hero(
  tag: 'product-${product.id}',
  child: Image.network(product.imageUrl),
)

// Destination screen
Hero(
  tag: 'product-${product.id}',
  child: Image.network(product.imageUrl),
)

// Custom Hero flight
Hero(
  tag: 'avatar',
  flightShuttleBuilder: (
    flightContext,
    animation,
    flightDirection,
    fromHeroContext,
    toHeroContext,
  ) {
    return AnimatedBuilder(
      animation: animation,
      builder: (context, _) {
        return CircleAvatar(
          radius: lerpDouble(40, 60, animation.value),
        );
      },
    );
  },
  child: CircleAvatar(),
)
```

## 4. Staggered Animations

```dart
class StaggeredList extends StatefulWidget {
  @override
  State<StaggeredList> createState() => _StaggeredListState();
}

class _StaggeredListState extends State<StaggeredList>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  final List<Animation<Offset>> _animations = [];

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(milliseconds: 1000),
      vsync: this,
    );

    // Create staggered animations
    for (int i = 0; i < 5; i++) {
      final start = i * 0.1;
      final end = start + 0.4;
      _animations.add(
        Tween<Offset>(begin: Offset(1, 0), end: Offset.zero).animate(
          CurvedAnimation(
            parent: _controller,
            curve: Interval(start, end, curve: Curves.easeOut),
          ),
        ),
      );
    }

    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: List.generate(5, (index) {
        return SlideTransition(
          position: _animations[index],
          child: ListTile(title: Text('Item $index')),
        );
      }),
    );
  }
}
```

## 5. Physics-Based Animations

```dart
// Spring simulation
class SpringAnimation extends StatefulWidget {
  @override
  State<SpringAnimation> createState() => _SpringAnimationState();
}

class _SpringAnimationState extends State<SpringAnimation>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  late Animation<double> _animation;

  final SpringDescription spring = SpringDescription(

Related in General