Skip to main content

awesome_scroll_actions 2.1.0 copy "awesome_scroll_actions: ^2.1.0" to clipboard
awesome_scroll_actions: ^2.1.0 copied to clipboard

Awesome Scroll Actions dial. An arc of action pills you spin with a vertical drag, tuck away with a side pull, and select with a tap.

example/lib/main.dart

import 'dart:math' as math;

import 'package:awesome_scroll_actions/awesome_scroll_actions.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(const AwesomeScrollDemoApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Awesome Scroll Actions',
      debugShowCheckedModeBanner: false,
      // The dial picks its palette off whichever ThemeData is in force, so
      // registering both makes it follow the system light/dark switch.
      theme: ThemeData(
        colorSchemeSeed: const Color(0xFF1A2A3A),
        extensions: const [AwesomeScrollActionsTheme()],
      ),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        colorSchemeSeed: const Color(0xFF1A2A3A),
        extensions: const [AwesomeScrollActionsTheme.dark],
      ),
      themeMode: ThemeMode.system,
      // The dial is drawn for a phone. A desktop browser window would
      // stretch it across the full viewport, so on anything wider than a
      // tablet the demo sits in a phone-shaped frame instead. The widget
      // itself measures with a LayoutBuilder, so bounding it is enough.
      builder: (context, child) {
        final size = MediaQuery.sizeOf(context);
        if (size.width < 600) return child!;
        return ColoredBox(
          color: const Color(0xFF0E1620),
          child: Center(
            child: PhysicalModel(
              color: Colors.black,
              borderRadius: BorderRadius.circular(32),
              elevation: 12,
              clipBehavior: Clip.antiAlias,
              child: SizedBox(
                width: 390,
                // Shrink to fit a short window rather than overflowing it.
                height: math.min(844, size.height - 48),
                child: child,
              ),
            ),
          ),
        );
      },
      home: const AwesomeScrollActionsScreen(),
    );
  }
}

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

  @override
  State<AwesomeScrollActionsScreen> createState() => _AwesomeScrollActionsScreenState();
}

class _AwesomeScrollActionsScreenState extends State<AwesomeScrollActionsScreen> {
  final _controller = QuickActionsController();
  bool _showGuide = true;

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

  void _open(QuickAction action, int index) {
    // Route to the real flow here, e.g. Navigator.pushNamed(context, '/${action.id}').
    debugPrint('Quick action: ${action.id}');
  }

  @override
  Widget build(BuildContext context) {
    final dark = Theme.of(context).brightness == Brightness.dark;
    return AnnotatedRegion<SystemUiOverlayStyle>(
      value: dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark,
      child: Scaffold(
        // The dial laid over the app's own page: `showBackground: false`
        // drops its gradient and the scrim dims the page behind it as the
        // dial is pulled out. Tap the edge handle or drag sideways.
        body: Stack(
          children: [
            const _AccountPage(),
            GestureDetector(
              // Long-press anywhere to toggle the arc guide while tuning.
              onLongPress: () => setState(() => _showGuide = !_showGuide),
              child: AwesomeScrollActions(
                actions: AwesomeScrollDefaults.actions,
                initialActionId: AwesomeScrollDefaults.initialActionId,
                controller: _controller,
                showGuideLine: _showGuide,
                showBackground: false,
                startTucked: true,
                // arc: QuickActionsArc.horizontal,
                onActionSelected: _open,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// Stand-in for the host app's page, so the scrim has something to dim. Its
/// list starts below the dial's own header and stat card rather than
/// printing a second balance under them.
class _AccountPage extends StatelessWidget {
  const _AccountPage();

  static const _rows = [
    ('Salary – CBT Bank', '+ 2,400,000', 'Today'),
    ('Luku token', '- 30,000', 'Today'),
    ('Ramadhani M.', '- 145,000', 'Yesterday'),
    ('Azam TV', '- 32,000', 'Yesterday'),
    ('Fatuma S.', '+ 80,000', 'Mon'),
    ('Vodacom bundle', '- 10,000', 'Mon'),
    ('Water bill', '- 18,500', 'Sun'),
  ];

  @override
  Widget build(BuildContext context) {
    final qa = Theme.of(context).extension<AwesomeScrollActionsTheme>()!;
    return ColoredBox(
      color: qa.backgroundTop,
      child: SafeArea(
        child: ListView(
          padding: const EdgeInsets.fromLTRB(26, 300, 26, 24),
          children: [
            Text('Recent',
                style: TextStyle(
                    fontSize: 15, fontWeight: FontWeight.w700, color: qa.titleColor)),
            for (final (name, amount, day) in _rows)
              ListTile(
                contentPadding: EdgeInsets.zero,
                title: Text(name, style: TextStyle(fontSize: 15, color: qa.titleColor)),
                subtitle: Text(day, style: TextStyle(color: qa.mutedColor)),
                trailing: Text(
                  amount,
                  style: TextStyle(
                    fontWeight: FontWeight.w700,
                    color: amount.startsWith('+')
                        ? (qa.backgroundTop.computeLuminance() > 0.5
                            ? const Color(0xFF1B7F4B)
                            : const Color(0xFF4ECB8B))
                        : qa.titleColor,
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}
1
likes
150
points
596
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Awesome Scroll Actions dial. An arc of action pills you spin with a vertical drag, tuck away with a side pull, and select with a tap.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on awesome_scroll_actions