enhanced_speed_dial 1.0.0 copy "enhanced_speed_dial: ^1.0.0" to clipboard
enhanced_speed_dial: ^1.0.0 copied to clipboard

A highly customizable Flutter speed dial with advanced blur effects, flexible positioning, multiple directions, comprehensive styling options, and smooth animations.

example/lib/main.dart

/// Example app demonstrating the Enhanced Speed Dial package
library;

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Enhanced Speed Dial Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ExampleScreen(),
    );
  }
}

class ExampleScreen extends StatefulWidget {
  const ExampleScreen({super.key});

  @override
  State<ExampleScreen> createState() => _ExampleScreenState();
}

class _ExampleScreenState extends State<ExampleScreen> {
  String _lastAction = 'No action yet';
  bool _useSimpleVersion = true;
  SpeedDialCorner _selectedCorner = SpeedDialCorner.bottomRight;
  SpeedDialDirection _selectedDirection = SpeedDialDirection.up;
  bool _showBlurBackground = true;
  double _blurIntensity = 10.0;
  bool _isDialOpen = false;

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        duration: const Duration(seconds: 2),
        behavior: SnackBarBehavior.floating,
      ),
    );
    setState(() {
      _lastAction = message;
    });
  }

  String _getCornerName(SpeedDialCorner corner) {
    switch (corner) {
      case SpeedDialCorner.topLeft:
        return 'Top Left';
      case SpeedDialCorner.topRight:
        return 'Top Right';
      case SpeedDialCorner.bottomLeft:
        return 'Bottom Left';
      case SpeedDialCorner.bottomRight:
        return 'Bottom Right';
    }
  }

  String _getDirectionName(SpeedDialDirection direction) {
    switch (direction) {
      case SpeedDialDirection.up:
        return 'Up';
      case SpeedDialDirection.down:
        return 'Down';
      case SpeedDialDirection.left:
        return 'Left';
      case SpeedDialDirection.right:
        return 'Right';
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Enhanced Speed Dial Example'),
        actions: [
          TextButton(
            onPressed: () {
              setState(() {
                _useSimpleVersion = !_useSimpleVersion;
              });
            },
            child: Text(
              _useSimpleVersion ? 'Advanced' : 'Simple',
            ),
          ),
        ],
      ),
      body: Stack(
        children: [
          Center(
            child: SingleChildScrollView(
              padding: const EdgeInsets.all(20.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    _useSimpleVersion
                        ? 'Simple Configuration'
                        : 'Advanced Configuration',
                    style: const TextStyle(
                        fontSize: 24, fontWeight: FontWeight.bold),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 10),
                  Text(
                    _useSimpleVersion
                        ? 'Minimal setup with auto-generated colors and hero tags'
                        : 'Full customization with explicit styling',
                    style: const TextStyle(fontSize: 16),
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 20),
                  // Configuration Controls
                  if (!_useSimpleVersion) ...[
                    Card(
                      elevation: 2,
                      child: Padding(
                        padding: const EdgeInsets.all(16.0),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            const Text(
                              'Configuration',
                              style: TextStyle(
                                fontSize: 18,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            const SizedBox(height: 16),

                            // Corner selector
                            const Text('Position Corner:',
                                style: TextStyle(fontWeight: FontWeight.bold)),
                            const SizedBox(height: 8),
                            Wrap(
                              spacing: 8,
                              children: SpeedDialCorner.values.map((corner) {
                                return ChoiceChip(
                                  label: Text(_getCornerName(corner)),
                                  selected: _selectedCorner == corner,
                                  onSelected: (selected) {
                                    if (selected) {
                                      setState(() {
                                        _selectedCorner = corner;
                                      });
                                    }
                                  },
                                );
                              }).toList(),
                            ),
                            const SizedBox(height: 16),

                            // Direction selector
                            const Text('Expand Direction:',
                                style: TextStyle(fontWeight: FontWeight.bold)),
                            const SizedBox(height: 8),
                            Wrap(
                              spacing: 8,
                              children:
                                  SpeedDialDirection.values.map((direction) {
                                return ChoiceChip(
                                  label: Text(_getDirectionName(direction)),
                                  selected: _selectedDirection == direction,
                                  onSelected: (selected) {
                                    if (selected) {
                                      setState(() {
                                        _selectedDirection = direction;
                                      });
                                    }
                                  },
                                );
                              }).toList(),
                            ),
                            const SizedBox(height: 16),

                            // Blur settings
                            Row(
                              children: [
                                const Text('Blur Background:'),
                                const SizedBox(width: 8),
                                Switch(
                                  value: _showBlurBackground,
                                  onChanged: (value) {
                                    setState(() {
                                      _showBlurBackground = value;
                                    });
                                  },
                                  key: const ValueKey('blur_switch'),
                                ),
                              ],
                            ),
                            if (_showBlurBackground) ...[
                              const SizedBox(height: 8),
                              Row(
                                children: [
                                  const Text('Blur Intensity:'),
                                  const SizedBox(width: 8),
                                  Expanded(
                                    child: Slider(
                                      value: _blurIntensity,
                                      min: 1.0,
                                      max: 20.0,
                                      divisions: 19,
                                      label: _blurIntensity.round().toString(),
                                      onChanged: (value) {
                                        setState(() {
                                          _blurIntensity = value;
                                        });
                                      },
                                      key: const ValueKey('blur_slider'),
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          ],
                        ),
                      ),
                    ),
                    const SizedBox(height: 20),
                  ],

                  // Features Card
                  Container(
                    padding: const EdgeInsets.all(16),
                    decoration: BoxDecoration(
                      color: Colors.grey[100],
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Column(
                      children: [
                        const Text(
                          'Features Demonstrated:',
                          style: TextStyle(
                              fontSize: 18, fontWeight: FontWeight.w600),
                        ),
                        const SizedBox(height: 10),
                        if (_useSimpleVersion) ...[
                          const Text('• SpeedDialOption.simple() constructor'),
                          const Text('• Auto-generated colors'),
                          const Text('• Auto-generated hero tags'),
                          const Text('• Minimal configuration'),
                        ] else ...[
                          const Text('• Full customization options'),
                          const Text('• Custom colors and styling'),
                          const Text('• Individual option settings'),
                          const Text('• Advanced animations'),
                          const Text('• All corner positioning'),
                          const Text('• All direction expansions'),
                          const Text('• Configurable blur effects'),
                        ],
                      ],
                    ),
                  ),
                  const SizedBox(height: 30),
                ],
              ),
            ),
          ),
          // Place the speed dial as a positioned widget instead of floatingActionButton
          if (!_useSimpleVersion) _buildAdvancedSpeedDial(),
        ],
      ),
      floatingActionButton: _useSimpleVersion ? _buildSimpleSpeedDial() : null,
    );
  }

  // Simple version with minimal configuration
  Widget _buildSimpleSpeedDial() {
    return EnhancedSpeedDial.simple(
      mainIcon: Icons.menu,
      applySafeArea: false, // Required when used as floatingActionButton
      options: [
        SpeedDialOption.simple(
          label: 'Create',
          icon: Icons.add,
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Create tapped (simple)');
          },
        ),
        SpeedDialOption.simple(
          label: 'Edit',
          icon: Icons.edit,
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Edit tapped (simple)');
          },
        ),
        SpeedDialOption.simple(
          label: 'Share',
          icon: Icons.share,
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Share tapped (simple)');
          },
        ),
        SpeedDialOption.simple(
          label: 'Settings',
          icon: Icons.settings,
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Settings tapped (simple)');
          },
        ),
      ],
    );
  }

  // Advanced version with full customization
  Widget _buildAdvancedSpeedDial() {
    return EnhancedSpeedDial(
      mainIcon: Icons.add,
      openIcon: Icons.close,
      backgroundColor: Colors.blue,
      foregroundColor: Colors.white,
      showBlurBackground: _showBlurBackground,
      blurIntensity: _blurIntensity,
      blurOverlayColor: const Color.fromRGBO(0, 0, 0, 0.3),
      heroTag: "example_speed_dial",
      tooltip: "Open speed dial",
      animationDuration: const Duration(milliseconds: 300),
      animationCurve: Curves.easeInOutBack,
      corner: _selectedCorner, // Use selected corner
      direction: _selectedDirection, // Use selected direction
      optionSpacing: 12.0,
      mainToOptionSpacing: 24.0, // Better spacing from main FAB to first option
      labelSpacing: 16.0,
      fabSize: 56.0,
      optionFabSize: 48.0,
      elevation: 8.0,
      rotateMainFab: true,
      rotationAngle: 3.14159, // π radians (180 degrees)
      closeOnOptionTap: true,
      closeOnBlurTap: true,
      showLabels: true,
      applySafeArea: true, // Enable free positioning for all corners
      labelStyle: const TextStyle(
        fontWeight: FontWeight.w500,
        fontSize: 14,
      ),
      options: [
        SpeedDialOption(
          label: 'Create Note',
          icon: Icons.note_add,
          color: Colors.green,
          heroTag: "create_note",
          tooltip: "Create a new note",
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Create Note tapped (advanced)');
          },
          elevation: 4.0,
          size: 52.0,
        ),
        SpeedDialOption(
          label: 'Add Photo',
          icon: Icons.photo_camera,
          color: Colors.orange,
          heroTag: "add_photo",
          tooltip: "Add a photo",
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Add Photo tapped (advanced)');
          },
          elevation: 4.0,
        ),
        SpeedDialOption(
          label: 'Record Audio',
          icon: Icons.mic,
          color: Colors.red,
          heroTag: "record_audio",
          tooltip: "Record audio",
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Record Audio tapped (advanced)');
          },
          elevation: 6.0,
          splashColor: Colors.red.withValues(alpha: 0.3),
        ),
        SpeedDialOption(
          label: 'Share',
          icon: Icons.share,
          color: Colors.purple,
          heroTag: "share",
          tooltip: "Share content",
          onTap: () {
            // This option won't close the speed dial automatically
            _showSnackBar('Share tapped (advanced) - dial stays open');
          },
          elevation: 4.0,
          closeOnTap: false, // This option won't close the speed dial
        ),
        SpeedDialOption(
          label: 'Settings',
          icon: Icons.settings,
          color: Colors.indigo,
          heroTag: "settings",
          tooltip: "Open settings",
          onTap: () {
            setState(() {
              _isDialOpen = false;
            });
            _showSnackBar('Settings tapped (advanced)');
          },
          elevation: 4.0,
        ),
      ],
    );
  }
}
2
likes
150
points
31
downloads
screenshot

Publisher

verified publisherpixelplatforms.com

Weekly Downloads

A highly customizable Flutter speed dial with advanced blur effects, flexible positioning, multiple directions, comprehensive styling options, and smooth animations.

Repository (GitHub)
View/report issues

Topics

#speed-dial #floating-action-button #blur-background #material-design #flutter-widget

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on enhanced_speed_dial