flutter expandable menu item FAB
flutter expandable menu item FAB

Hi Guys, Welcome to Proto Coders Point. In this Flutter Tutorial will learn how to implement floating action button with popup FAB menu by using flutter_speed_dial package.

Floating Action Button(FAB)

In Flutter FAB is a round shape button that is floating at bottom right of your app mobile screen.

Flutter fab button is a primary action button event that a user commonly perform, but sometimes their can be some situation where user want to perform different event using fab menu in flutter.

In such case, developer can provide expandable FAB option, where when a user click on main FAB Button to expand floating action button spawns.

check out below fab expanding GIF Example

Here each fab menus can perform different event/action as defined.

Video Tutorial

Let’s get started

Flutter_Speed_Dial Package

The speed dial in flutter is animated transition of multiple Fab menu, which emits from a main FAB button when tapped/clicked (Expands multiple fab menu) & tapped again will absorb it back in it stack behind main fab button.

This floating button menu will have fab icons ( Animated Icons in FAB ) or ( Normal flutter icon) & a label to them.

Let’s start using flutter speed dial plugin into flutter app

Below are the steps to add speed dial package into flutter project as external library

Step 1: Adding flutter_speed_dial dependencies

Open pubspec.yaml file & add the fab button library under dependencies as shown below

dependencies:
  flutter_speed_dial:    # this line

Step 2: Run command to download above dependencies in flutter

Now, run a command in IDE terminal ‘flutter pub get’

C:\Android Studio Stuff\Flutter Project\fab_menu>flutter pub get

OR

hit pub get button on top pubspec.yaml file (Android Studio), this will download the package into your flutter project in external Libraries folder.

Step 3: import flutter_speed_dial.dart

Now, once dependencies is been added successfully, you need to import the plugin or package where you want to use it (say main.dart)

import 'package:flutter_speed_dial/flutter_speed_dial.dart';

Properities of speedDial widget

PropertiesUsage
animatedIcon:Define a animatedIcons, to show Fab Icon animation Eg: AnimatedIcons.menu_close.
backgroundColor:used to set a color to main FAb button. Eg: Colors.redAccent.
overlayColor:when FAB is open, overlay app content with light Color Eg: Colors.grey.
overLayOpacity:Set a opacity of overlayColor.
spacingGive some spacing between main FAB button & it’s child SpeedDialChild
spaceBetweenChildrenspacing between SpeedDialChild
closeManually:true or false, if set to false user need to tap back on FAB button to close it,
is set to true by default ( user can tap anywhere on screen to dismiss opened FAB button)
children:[]you can list of Speed Dial Child, that are menu of fab options
SpeedDial(
          animatedIcon: AnimatedIcons.menu_close,
          openCloseDial: isDialOpen,
          backgroundColor: Colors.redAccent,
          overlayColor: Colors.grey,
          overlayOpacity: 0.5,
          spacing: 15,
          spaceBetweenChildren: 15,
          closeManually: true,
          children: [
            // add multiple SpeedDialChild
          ],
        ),

Properties of SpeedDialChild widget

PropertiesDescription
child:Show a Widget of child FAB. Eg: Icon(Icons.share_rounded)
label:give label text
backgroundColor: used to set a color to main FAb button. Eg: Colors.blue
onTap():is a callBack, event to perform when user Tap on the SpeedDialChild fab menu
SpeedDialChild(
              child: Icon(Icons.copy),
              label: 'Copy',
                onTap: (){
                  print('Copy Tapped');
                }
            )


Complete Source Code – Expandable floating action button menu popup

Will have used WillPopScope to prevent user from exiting the app if floating action menu’sw are open.

So if FAB is open & user press back button FAB button should get closed.

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  ValueNotifier<bool> isDialOpen = ValueNotifier(false);

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async{
          if(isDialOpen.value){
            isDialOpen.value = false;
            return false;
          }else{
            return true;
          }
      },
      child: Scaffold(
        floatingActionButton: SpeedDial(
          animatedIcon: AnimatedIcons.menu_close,
          openCloseDial: isDialOpen,
          backgroundColor: Colors.redAccent,
          overlayColor: Colors.grey,
          overlayOpacity: 0.5,
          spacing: 15,
          spaceBetweenChildren: 15,
          closeManually: true,
          children: [
            SpeedDialChild(
              child: Icon(Icons.share_rounded),
              label: 'Share',
              backgroundColor: Colors.blue,
              onTap: (){
                print('Share Tapped');
              }
            ),
            SpeedDialChild(
              child: Icon(Icons.mail),
              label: 'Mail',
                onTap: (){
                  print('Mail Tapped');
                }
            ),
            SpeedDialChild(
              child: Icon(Icons.copy),
              label: 'Copy',
                onTap: (){
                  print('Copy Tapped');
                }
            ),
          ],
        ),
        body: Container(
          alignment: Alignment.center,
          child: const Text("FAB Menu Example",style: TextStyle(fontSize: 30),),
        ),
      ),
    );
  }
}