36

Is there any ready made widget or where to get started floating action button with speed dial actions in Flutter.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83
  • Hijacking this post to show this plugin: https://pub.dartlang.org/packages/unicorndial – Zroq Jul 01 '18 at 12:05

2 Answers2

82

Here's a sketch of how to implement a Speed dial using FloatingActionButton.

video

import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  AnimationController _controller;

  static const List<IconData> icons = const [ Icons.sms, Icons.mail, Icons.phone ];

  @override
  void initState() {
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );
  }

  Widget build(BuildContext context) {
    Color backgroundColor = Theme.of(context).cardColor;
    Color foregroundColor = Theme.of(context).accentColor;
    return new Scaffold(
      appBar: new AppBar(title: new Text('Speed Dial Example')),
      floatingActionButton: new Column(
        mainAxisSize: MainAxisSize.min,
        children: new List.generate(icons.length, (int index) {
          Widget child = new Container(
            height: 70.0,
            width: 56.0,
            alignment: FractionalOffset.topCenter,
            child: new ScaleTransition(
              scale: new CurvedAnimation(
                parent: _controller,
                curve: new Interval(
                  0.0,
                  1.0 - index / icons.length / 2.0,
                  curve: Curves.easeOut
                ),
              ),
              child: new FloatingActionButton(
                heroTag: null,
                backgroundColor: backgroundColor,
                mini: true,
                child: new Icon(icons[index], color: foregroundColor),
                onPressed: () {},
              ),
            ),
          );
          return child;
        }).toList()..add(
          new FloatingActionButton(
            heroTag: null,
            child: new AnimatedBuilder(
              animation: _controller,
              builder: (BuildContext context, Widget child) {
                return new Transform(
                  transform: new Matrix4.rotationZ(_controller.value * 0.5 * math.pi),
                  alignment: FractionalOffset.center,
                  child: new Icon(_controller.isDismissed ? Icons.share : Icons.close),
                );
              },
            ),
            onPressed: () {
              if (_controller.isDismissed) {
                _controller.forward();
              } else {
                _controller.reverse();
              }
            },
          ),
        ),
      ),
    );
  }
}
Andrei Volgin
  • 40,755
  • 6
  • 49
  • 58
Collin Jackson
  • 110,240
  • 31
  • 221
  • 152
  • 1
    Sometimes, android emulator does not load material icons http://g.recordit.co/NKUvsdfdwO.gif is that known issue? – Kyaw Tun Sep 29 '17 at 02:55
  • You should make sure your pubspec.yaml indicates the app uses material design. There are some known issues with Android emulators, you can search github for them. – Collin Jackson Sep 29 '17 at 03:06
  • Yes it is `uses-material-design: true`, but still have problem sometimes. – Kyaw Tun Sep 29 '17 at 03:25
  • When i use above code getting crash. There are multiple heroes that share the same tag within a subtree. Within each subtree for which heroes are to be animated (typically a PageRoute subtree), each Hero must have a unique non-null tag. In this case, multiple heroes had the following tag: Here is the subtree for one of the offending heroes: – Magesh Pandian Jul 10 '18 at 02:26
  • 2
    @MageshPandian to solve that error just add `heroTag: null,` to each FloatingActionButton. – Patrick Boos Jul 13 '18 at 12:02
  • Each button will do the same onPressed in this code because it's aim is to access a speed dial feature? I was able to change this code so that each button did a unique onPressed using the 2nd answer below as a guide. Thanks for the example code and the learning opportunity! – Andrew Caprario Jun 05 '20 at 21:19
  • You could have used `AnimatedIcon` instead :) – Daksh Gargas Apr 16 '21 at 14:30
20

This plugin could serve you: https://pub.dartlang.org/packages/flutter_speed_dial

You need declare the dependency in the pubspect.yaml file

dependencies:
  flutter:
    sdk: flutter
  flutter_speed_dial: ^1.0.9

Here is an example:

Widget build(BuildContext context) {
return Scaffold(
    floatingActionButton: SpeedDial(
      animatedIcon: AnimatedIcons.menu_close,
      animatedIconTheme: IconThemeData(size: 22.0),
      // this is ignored if animatedIcon is non null
      // child: Icon(Icons.add),
      visible: _dialVisible,
      curve: Curves.bounceIn,
      overlayColor: Colors.black,
      overlayOpacity: 0.5,
      onOpen: () => print('OPENING DIAL'),
      onClose: () => print('DIAL CLOSED'),
      tooltip: 'Speed Dial',
      heroTag: 'speed-dial-hero-tag',
      backgroundColor: Colors.white,
      foregroundColor: Colors.black,
      elevation: 8.0,
      shape: CircleBorder(),
      children: [
        SpeedDialChild(
          child: Icon(Icons.accessibility),
          backgroundColor: Colors.red,
          label: 'First',
          labelStyle: TextTheme(fontSize: 18.0),
          onTap: () => print('FIRST CHILD')
        ),
        SpeedDialChild(
          child: Icon(Icons.brush),
          backgroundColor: Colors.blue,
          label: 'Second',
          labelStyle: TextTheme(fontSize: 18.0),
          onTap: () => print('SECOND CHILD'),
        ),
        SpeedDialChild(
          child: Icon(Icons.keyboard_voice),
          backgroundColor: Colors.green,
          label: 'Third',
          labelStyle: TextTheme(fontSize: 18.0),
          onTap: () => print('THIRD CHILD'),
        ),
      ],
    ),
);
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Julian Sanchez
  • 567
  • 6
  • 6