How to Make Draggable and Expandable Floating Action Menu in Flutter

To create a draggable and expandable floating action menu in Flutter, we can use a combination of the Stack, AnimatedContainer, and GestureDetector widgets.

Here’s an example code snippet that demonstrates how to make a draggable and expandable floating action menu in Flutter:

import 'package:flutter/material.dart';

void main() {
  runApp( MyFABMenuScreen());
}


class MyFABMenuScreen extends StatefulWidget {
  @override
  _MyFABMenuScreenState createState() => _MyFABMenuScreenState();
}

class _MyFABMenuScreenState extends State<MyFABMenuScreen>
    with SingleTickerProviderStateMixin {
  bool _isExpanded = false;
  double _bottomPadding = 20.0;
  double _menuHeight = 200.0;
  late AnimationController _animationController;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500));
    _animation =
        CurvedAnimation(parent: _animationController, curve: Curves.easeInOut);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('flutterfever fab Menu'),
        ),
        body: Center(
          child: Text('flutterfever FAB Menu Screen'),
        ),
        floatingActionButton: GestureDetector(
          onVerticalDragUpdate: (details) {
            setState(() {
              _menuHeight -= details.delta.dy;
            });
          },
          onVerticalDragEnd: (details) {
            if (_menuHeight < 50.0) {
              _isExpanded = false;
              _bottomPadding = 20.0;
              _menuHeight = 200.0;
              _animationController.reverse();
            } else {
              _isExpanded = true;
              _bottomPadding = 100.0;
              _animationController.forward();
            }
          },
          child: AnimatedContainer(
            duration: Duration(milliseconds: 500),
            curve: Curves.easeInOut,
            height: _menuHeight,
            child: Stack(
              children: [
                Positioned(
                  bottom: _bottomPadding,
                  right: 20.0,
                  child: ScaleTransition(
                    scale: _animation,
                    child: FloatingActionButton(
                      onPressed: () {},
                      child: Icon(Icons.edit),
                    ),
                  ),
                ),
                Positioned(
                  bottom: _bottomPadding,
                  right: 20.0,
                  child: ScaleTransition(
                    scale: _animation,
                    child: FloatingActionButton(
                      onPressed: () {},
                      child: Icon(Icons.camera_alt),
                    ),
                  ),
                ),
                Positioned(
                  bottom: _bottomPadding,
                  right: 20.0,
                  child: FloatingActionButton(
                    onPressed: () {
                      if (_isExpanded) {
                        _isExpanded = false;
                        _bottomPadding = 20.0;
                        _menuHeight = 200.0;
                        _animationController.reverse();
                      } else {
                        _isExpanded = true;
                        _bottomPadding = 100.0;
                        _menuHeight = 300.0;
                        _animationController.forward();
                      }
                    },
                    child: Icon(_isExpanded ? Icons.close : Icons.menu),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

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

output without draggable:

with draggable screen:

In the code above, we added a GestureDetector widget as the floatingActionButton of the Scaffold widget. Inside the GestureDetector, we added an AnimatedContainer widget to represent the expandable menu. We also defined a _isExpanded variable to keep track of whether the menu is expanded

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More