Flutter Pro Design

Small details that build taste in Flutter.

curated by Kamran BekirovKamran Bekirov

Make button presses feel right

Check these button press animations from expen.app. Notice how the one with spring physics feels more natural, like a real object reacting to your touch:

In the previous detail I showed Flutter's built-in spring physics support. Worth reading it first if you're new to springs.

Here I'll skip the hand-tuning SpringDescription and use motor instead. It ships with iOS spring presets and Material 3 motion tokens, each tuned to match its platform's natural motion.

Just use SingleMotionBuilder from the package. It animates a value to a target using the spring you pick:

SingleMotionBuilder(
  // autocomplete to see other variants, MaterialSpringMotion too
  motion: CupertinoMotion.smooth(),
  value: _scale,
  builder: (context, scale, child) {
    return Transform.scale(
      scale: scale, 
      child: child
    );
  },
  child: widget.child,
);

Or even make it a reusable widget:

class Pressable extends StatefulWidget {
  final VoidCallback? onTap;
  final Widget child;
  
  const Pressable({
    super.key, 
    this.onTap, 
    required this.child,
  });
  
  @override
  State<Pressable> createState() => _PressableState();
}

class _PressableState extends State<Pressable> {
  double _scale = 1.0;
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.onTap,
      onTapDown: (_) {
        setState(() {
          _scale = 0.96;
        });
      },
      onTapUp: (_) {
        setState(() {
          _scale = 1.0;
        });
      },
      onTapCancel: () {
        setState(() {
          _scale = 1.0;
        });
      },
      child: SingleMotionBuilder(
        motion: CupertinoMotion.smooth(),
        value: _scale,
        builder: (context, scale, child) {
          return Transform.scale(
            scale: scale, 
            child: child,
          );
        },
        child: widget.child,
      ),
    );
  }
}

Using one spring across platforms is fine, they are high-quality standards. If you want users to feel more at home, use CupertinoMotion on iOS/macOS, and MaterialSpringMotion on the rest.