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

Modal sheets that slide in from the top, like an app bar dropdown. Awaitable, dismissible, with a configurable barrier, curves and duration.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'modal_top_sheet example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  static const List<String> _languages = <String>[
    'Polski',
    'English',
    'Deutsch',
  ];

  String _language = 'Polski';

  /// The sheet returns what the user picked, like any other Flutter modal.
  Future<void> _pickLanguage() async {
    final String? picked = await showModalTopSheet<String>(
      context,
      child: _LanguageSheet(languages: _languages, selected: _language),
    );
    if (picked != null && mounted) {
      setState(() => _language = picked);
    }
  }

  Future<void> _showBlocking() => showModalTopSheet<void>(
    context,
    // Neither a tap on the barrier nor a system back closes this one.
    isDismissible: false,
    barrierColor: Colors.black54,
    child: Builder(
      builder: (BuildContext context) => _Sheet(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            const Text('This one can only be closed from inside.'),
            const SizedBox(height: 12),
            FilledButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('Close'),
            ),
          ],
        ),
      ),
    ),
  );

  Future<void> _showSlow() => showModalTopSheet<void>(
    context,
    duration: const Duration(milliseconds: 900),
    curve: Curves.elasticOut,
    reverseCurve: Curves.easeInBack,
    padding: const EdgeInsets.only(top: 120),
    barrierColor: Colors.indigo.withValues(alpha: 0.3),
    child: const _Sheet(child: Text('Slower, springier, lower.')),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('modal_top_sheet')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Language: $_language',
              style: Theme.of(context).textTheme.titleMedium,
            ),
            const SizedBox(height: 24),
            FilledButton(
              onPressed: _pickLanguage,
              child: const Text('Pick a language'),
            ),
            const SizedBox(height: 12),
            OutlinedButton(
              onPressed: _showBlocking,
              child: const Text('Non-dismissible sheet'),
            ),
            const SizedBox(height: 12),
            OutlinedButton(
              onPressed: _showSlow,
              child: const Text('Custom curve and padding'),
            ),
          ],
        ),
      ),
    );
  }
}

/// A card the sheets share, so the demo shows content rather than chrome.
class _Sheet extends StatelessWidget {
  const _Sheet({required this.child});

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: const EdgeInsets.symmetric(horizontal: 16),
      child: Padding(padding: const EdgeInsets.all(24), child: child),
    );
  }
}

class _LanguageSheet extends StatelessWidget {
  const _LanguageSheet({required this.languages, required this.selected});

  final List<String> languages;
  final String selected;

  @override
  Widget build(BuildContext context) {
    return _Sheet(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          for (final String language in languages)
            ListTile(
              title: Text(language),
              trailing: language == selected ? const Icon(Icons.check) : null,
              onTap: () => Navigator.of(context).pop(language),
            ),
        ],
      ),
    );
  }
}
1
likes
160
points
91
downloads

Documentation

API reference

Publisher

verified publisherbomsamdi.com

Weekly Downloads

Modal sheets that slide in from the top, like an app bar dropdown. Awaitable, dismissible, with a configurable barrier, curves and duration.

Repository (GitHub)
View/report issues

Topics

#modal #sheet #navigation #widget #ui

License

MIT (license)

Dependencies

flutter

More

Packages that depend on modal_top_sheet