sheetify 1.0.0+1 copy "sheetify: ^1.0.0+1" to clipboard
sheetify: ^1.0.0+1 copied to clipboard

A Flutter package that provides customizable bottom sheet widgets with snapping behaviors, gesture support, animation, and dynamic state control.

📦 Sheetify #

Sheetify is a Flutter package that provides powerful and customizable bottom sheet widgets with snapping behaviors, gesture support, animation, and dynamic state control.
It’s ideal for building screens or improving modal interactions, menus, and custom dialogs using animated, scrollable draggable sheets.

This package exposes two main widgets:

  • MultiStateSheet: A sheet supporting multiple snap positions and states.
  • ToggleSheet: A sheet with toggleable open/close states.

Both widgets are controlled via their respective controllers and support custom configurations.

✨ Features #

  • 📀 Multi-state snapping — Define multiple anchors and snap between them using configurable behaviors.

Each MultiStateSheetController requires a SnappingBehavior and a StateMapper, enabling fine-tuned control over how the sheet responds to gestures and transitions. Available snapping behaviors include:

  • SizeSnappingBehavior: Defines snapping points in pixels.
  • FractionSnappingBehavior: Uses fractions of the viewport height.
  • ComponentsSnappingBehavior: Calculates offsets based on component sizes (e.g., header, footer).
  • MultiSnappingBehavior: Combines multiple snapping models for flexible layouts.

You can also create custom SnappingBehavior and SnappingModel implementations to define your own snapping logic tailored to unique layout requirements.

  • 🌺 Toggle control — Easily open or close sheets using ToggleSheetController.
  • 🌀 Interpolated animations — React to sheet transitions for custom visuals.
  • 🎮 Controllers — Programmatically snap or toggle sheets.
  • 📜 Barrier customization — Customize sheet fog/overlay with barrierColorDelegate.
  • 🔀 Gesture integration — Smooth drag, scroll, and snap behavior.
  • 🧱 Composable UI — Modular architecture to build complex layouts.
  • 🤲 Both modal and persistent use cases supported.

📦 Getting Started #

Add this to your pubspec.yaml:

dependencies:
  sheetify: ^1.0.0

Then import it:

import 'package:sheetify/sheetify.dart';

Lint Rules with sheetify_lint #

To help enforce best practices, we provide a companion linter package: sheetify_lint.

  • Your application must contain an analysis_options.yaml with the following:
analyzer:
  plugins:
    - custom_lint
  • And needs a custom_lint and sheetify_lint packages as dev_dependencies:
dev_dependencies:
  custom_lint: ^0.8.0
  sheetify_lint: ^1.0.1

📐 Sheet Layout Structure #

Here's how the layout inside a MultiStateSheet or ToggleSheet is structured: [Sheetify Layout Diagram]

📘 Usage #

MultiStateSheet #

import 'package:sheetify/sheetify.dart';

final controller = MultiStateSheetController<YourStateMapper>(
  behavior: YourSnappingBehavior(),
  stateMapper: YourStateMapper(),
);

MultiStateSheet<YourStateMapper>(
  scrollController: controller,
  barrierColorDelegate: YourStateMapper.barrierColorDelegate,
  resizeToAvoidViewPadding: true,
  hitTestBehavior: HitTestBehavior.opaque,
  backgroundColor: Colors.white,
  topHeader: YourAnimatedHeader(),
  header: YourHeader(),
  footer: YourFooter(),
  outsideOpacityDelegate: YourStateMapper.outsideOpacityDelegate,
  outside: YourOutsideWidget(),
  sliver: DecoratedSliver(
    decoration: BoxDecoration(
      color: Colors.grey.shade300,
    ),
    sliver: SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => ListTile(title: Text('Item #\$index')),
        childCount: 20,
      ),
    ),
  ),
)

ToggleSheet #

final controller = ToggleSheetController();

ToggleSheet(
  scrollController: controller,
  backgroundColor: Colors.white,
  safeAreaColor: Colors.white,
  barrierColorDelegate: ToggleSheetDelegate.func(
    (controller) => Colors.black.withOpacity(controller.interpolation * 0.6),
  ),
  hitTestBehavior: HitTestBehavior.opaque,
  topHeader: const SizedBox(
    height: 10,
    width: double.infinity,
    child: ColoredBox(color: Colors.amber),
  ),
  topHeaderOffset: 10,
  offsetOutsideWidgetByTopheader: false,
  header: YourHeader(),
  footer: SizedBox(
    height: 100,
    child: GestureDetector(
      onTap: () {
        controller.reset();
        Navigator.of(context).pop();
      },
      child: const PlaceholderContainer(text: 'Close'),
    ),
  ),
  content: [
    const PlaceholderContainer(text: 'Content 1'),
    const PlaceholderContainer(text: 'Content 2'),
  ],
)

🎨 Animated Components #

Use built-in base classes to create animated widgets that respond to sheet state and interpolation:

class FadingHeader extends SheetAnimatedWidget<FourStateSheet> {
  const FadingHeader({super.key}) : super(defaultState: FourStateSheet.halfOpen);

  @override
  Widget build(BuildContext context, FourStateSheet state, double interpolation) {
    return Opacity(
      opacity: (interpolation),
      child: Text('My Header'),
    );
  }
}

or #

class FadingHeader extends SheetValueNotifierWidget<FourStateSheet> {
  const FadingHeader({super.key}) : super(defaultState: FourStateSheet.halfOpen);

  @override
  Widget build(BuildContext context, ValueNotifier<FourStateSheet> state, ValueNotifier<double> interpolation) {
    return FadeTransition(
      opacity: Animation.fromValueListenable(interpolation),
      child: Text('My Header'),
    );
  }
}

🧩 Sheetify Building Blocks #

Class Description
MultiStateSheet A bottom sheet that can snap between multiple predefined states (positions). It supports draggable behavior, animated transitions, slivers, custom headers/footers, and external gesture detection. Ideal for building flexible, state-driven UIs like modals or drawers.
MultiStateSheetController<StateType> Controls the state of a MultiStateSheet, allowing you to programmatically snap between defined states. Requires a SnappingBehavior and SheetStateMapper.
ToggleSheet A simpler sheet with two states: open and closed. Useful for expandable widgets like menus, drawers, or bottom actions. Supports slivers, headers, footers, and full customization of animation and gesture behavior.
ToggleSheetController Manages the state of a ToggleSheet, exposing open() and close() methods and additional properties. It can be initialized with a ToggleSheetHeightModel to define a maximum height constraint for the sheet. If not provided, the sheet will size itself based on its content, up to the available viewport height.
SnappingBehavior Abstract class used by MultiStateSheetController to define where the sheet should snap. Custom behaviors can be implemented by extending this class.
├─ SizeSnappingBehavior Snaps the sheet to specific heights (in logical pixels).
├─ FractionSnappingBehavior Snaps to a percentage of the viewport height.
├─ ComponentsSnappingBehavior Calculates snap points based on the height of header/footer/components.
└─ MultiSnappingBehavior Composes multiple snapping strategies for complex layouts.
SheetStateMapper<T> Maps a logical state (e.g. FourStateSheet.open) to a snap index and vice versa. Required for MultiStateSheetController. Also defines animation delegates like barrierColorDelegate.
ToggleSheetHeightModel defines the maximum height of a ToggleSheet, allowing it to maintain a consistent layout regardless of its content.
├─ ToggleSnappingConfig.fixed(double height) Sets the sheet height to an exact pixel value.
├─ ToggleSnappingConfig.offset(double offset) Calculates the sheet height based on its distance from the top of the screen.
└─ ToggleSnappingConfig.fraction(double fraction) Sets the sheet height as a fraction of the screen height.
SnapSheetStateComponent Base class for widgets that react to sheet state changes (e.g. headers that fade/resize). Extend this for interpolated animations.
├─ SheetAnimatedWidget<State> Provides state and interpolation to build animated widgets.
└─ SheetValueNotifierWidget<State> Provides ValueNotifiers of state/interpolation for animated builders.
ToggleSheetDelegate<T> A delegate class used to dynamically define properties (like color, shape, padding) based on the ToggleSheetController.

✅ Common Class Relationships #

MultiStateSheet → controlled by MultiStateSheetController, which depends on SnappingBehavior + SheetStateMapper<T>

ToggleSheet → controlled by ToggleSheetController, which depends on a ToggleSnappingConfig

Animated components → extend SheetAnimatedWidget<T> or SheetValueNotifierWidget<T> for state-aware UI

Delegates → such as ToggleSheetDelegate provide custom behavior for colors, padding, shapes, etc.

📱 Example App #

See the /example folder for a complete demo app showcasing:

  • Toggle sheet page with dynamic padding.
  • Modal Multi State Sheet.
  • Modal Toggle Sheet.

Try Demo

💡 Why Use Sheetify? #

  • Improves UX with interactive sheets.
  • Easily composable and extendable.
  • Works with both modal and persistent layout patterns
  • Lightweight, efficient and fully customizable.

🚀 Real-World Examples #

We are using Sheetify package inside Balady - Map application

[Dynamic Padding Toggle Sheet example] [Modal Toggle Sheet example] [Multi State Sheet example] [Multi State Sheet example]
  • Uses MultiStateSheet and ToggleSheet for most of the screens in the app.
  • Dynamic header and album art transitions
  • Gesture-driven drag and resize

🚧 Roadmap #

  • Add support for open directions for the sheets.

  • Improve accessibility and keyboard navigation.

  • Add controller route orchestrator to ensure smooth transitions between multiple sheet (similar behavior as a Hero widget).

🤝 Contribution #

Contributions are welcome! Please open issues for bugs or feature requests. Submit pull requests with clear descriptions and tests. See CONTRIBUTING.md for guidelines.

📜 License #

BSD-2 License. See LICENSE for details.

13
likes
0
points
684
downloads

Publisher

verified publisher2gis.ru

Weekly Downloads

A Flutter package that provides customizable bottom sheet widgets with snapping behaviors, gesture support, animation, and dynamic state control.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on sheetify