flutter_animate icon indicating copy to clipboard operation
flutter_animate copied to clipboard

Spring Based Animation

Open Solido opened this issue 1 year ago • 2 comments

Hi and happy new year, wish you a lot of great projects!

Flutter is following the exquisite Spring based animation.

Best implementation must be https://x.com/imadetheseworks/status/1876287026242490738.

How could we integrate it with Animate for instant wow marvel?

Thanks!

Solido avatar Jan 07 '25 20:01 Solido

Hi! I was mentioned here because I maintain springster and heroine. I'm glad to help out with an implementation if desired, I don't know if I'll have enough time in the near future to spearhead it though.

timcreatedit avatar Jan 08 '25 10:01 timcreatedit

I tried this implementation (simplified version of a button with a scale animation).

I'm not sure to go in the right direction. It seems possible, but it would be nice if .animate() accept a simulation.

import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:tap_builder/tap_builder.dart';

class CustomButton extends StatefulWidget {
  const CustomButton({super.key, required this.onTap});

  final VoidCallback onTap;

  @override
  State<CustomButton> createState() => _CustomButtonState();
}

class _CustomButtonState extends State<CustomButton>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();
    final spring = SpringDescription(mass: 200, stiffness: 80, damping: 8);
    final simulation = SpringSimulation(spring, 1, 0, 1);

    _controller = AnimationController.unbounded(vsync: this);
    _controller.animateWith(simulation);
  }

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

  @override
  Widget build(BuildContext context) {
    return TapBuilder(
      onTap: widget.onTap,
      builder: (context, state, _) {
        return Container(
              padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
              color: Colors.red,
              child: Text('Custom Button'),
            )
            .animate(
              controller: _controller,
              target: state == TapState.pressed ? 1 : 0.0,
            )
            .scale(
              duration: 400.ms,
              curve: Curves.easeInOutBack,
              begin: const Offset(1, 1),
              end: const Offset(1.05, 1.05),
              transformHitTests: false,
            );
      },
    );
  }
}

T-moz avatar Jun 19 '25 14:06 T-moz