smooth_sheets 0.11.1
smooth_sheets: ^0.11.1 copied to clipboard
Sheet widgets with smooth motion and great flexibility. Also supports nested navigation in both imperative and declarative ways.
smooth_sheets #
smooth_sheets offers modal and persistent sheet widgets for Flutter apps. The key features are:
- Smooth motion: The sheets respond to user interaction with smooth, graceful motion.
- Highly flexible: Not restricted to a specific design. Both modal and persistent styles are supported, as well as scrollable and non-scrollable widgets.
- Supports nested navigation: A sheet is able to have multiple pages and to navigate between the pages with motion animation for transitions.
- Works with imperative & declarative Navigator API: No special navigation mechanism is required. The traditional ways such as
Navigator.push
is supported and it works with Navigator 2.0 packages like go_route as well. - iOS flavor: The modal sheets in the style of iOS 15 are supported.
Migration guide #
Important
Version 0.11.x requires Flutter SDK version 3.27.0 or higher.
See here for older versions.
Showcases #
AI Playlist GeneratorAn AI assistant that helps create a music playlist based on the user's preferences. See the cookbook for more details. Key components:
|
|
Safari appA practical example of ios-style modal sheets. See the cookbook for more details. Key components:
|
|
Airbnb mobile app cloneA partial clone of the Airbnb mobile app. The user can drag the house list down to reveal the map behind it. See the cookbook for more details. Key components:
|
|
Todo ListA simple Todo app that shows how a sheet handles the on-screen keyboard. See the cookbook for more details. Used components:
|
Why use this? #
There are few packages on pub.dev that supports nested navigation with motion animation for page transitions. One of the great choices for this usecase is wolt_modal_sheet, which this package is inspired by. Although smooth_sheet has similar features with wolt_modal_sheet, it is not intended to be a replacement of that package. Here is some differences between those 2 packages:
wolt_modal_sheet | smooth_sheets | |
---|---|---|
Design | Based on Wolt's design guideline | Not restricted to a specific design, fully customizable |
Navigation mechanism | Manage the page index in ValueNotifier | Works with built-in Navigator API (both of imperative and declarative) |
Scrollable content | Supported | Supported |
Persistent sheets | Not supported | Supported |
Screen size adaptation | The sheet appears as a dialog on large screens | Not supported |
Usage #
Several resources are available for learning the functionalities of this package.
- Tutorials: See example/lib/tutorial/ to learn the basic usage of the core components.
- Showcases: More practical examples are available in example/lib/showcase/.
- Documentation: WORK IN PROGRESS!
Ingredients #
This section provides descriptions for each core component and links to related resources for further learning.
SheetOffset #
SheetOffset
represents a position of the sheet within the SheetViewport
where the sheet is rendered. It's used in various situations, e.g., specifing the initial position of the sheet or defining a set of positions to which the sheet should snap.
Sheet #
The basic sheet widget that can be dragged and scrollled. It can also size itself based on its content or stretched to fill available space.
See also:
- basic_sheet.dart for basic usage.
- scrollable_sheet.dart for usage with scrollable content.
- decorations.dart for styling examples.
PagedSheet #
See also:
- declarative_paged_sheet.dart, tutorial using go_router.
- imperative_paged_sheet.dart, tutorial using imperative Navigator API.
- paged_sheet_with_auto_route.dart, tutorial using auto_route.
Modal Sheets #
A sheet can be displayed as a modal sheet using ModalSheetRoute
for imperative navigation, or ModalSheetPage
for declarative navigation.
Furthermore, the modal sheets in the style of iOS 15 are also supported. For imperative navigation, use CupertinoModalSheetRoute
, and for declarative navigation, use CupertinoModalSheetPage
, respectively.
See also:
- SwipeDismissSensitivity, which can be used to tweak the sensitivity of the swipe-to-dismiss action.
- declarative_modal_sheet.dart, a tutorial of integration with declarative navigation using go_router package.
- imperative_modal_sheet.dart, a tutorial of integration with imperative Navigator API.
- cupertino_modal_sheet.dart, a tutorial of iOS style modal sheets.
- ios_style_declarative_modal_paged_sheet.dart, an example of iOS-style modal PagedSheet with go_router.
- showcase/todo_list, which uses SheetDismissible to show a confirmation dialog when the user tries to discard the todo editing sheet without saving the content.
SheetPhysics #
A physics determines how the sheet will behave when over-dragged or under-dragged, or when the user stops dragging. This is independent of the snapping behavior, which is configured via SheetSnapGrid. There are 2 predefined physics:
See also:
- physics_and_snap_grid.dart for basic usage.
SheetSnapGrid #
Determines how the sheet snaps to certain offsets when the user stops dragging or when an animation completes.
There are several predefined snap grid types:
See also:
- physics_and_snap_grid.dart for basic usage.
SheetController #
Like ScrollController for scrollable widget, the SheetController can be used to animate or observe the offset (position) of a sheet.
See also:
- sheet_controller.dart for basic usage.
SheetContentScaffold #
Simillar to the Scaffold, it offers the slots for a topBar
(like AppBar
) and a bottomBar
(like BottomNavigationBar
).
See also:
- SheetContentScaffold, the API documentation.
- BottomBarVisibility, which controls the visibility of the bottom bar based on sheet metrics (including offset).
- tutorial/sheet_content_scaffold.dart, which shows the basic usage of SheetContentScaffold.
- tutorial/bottom_bar_visibility.dart, which shows the basic usage of the
bottomBarVisibility
property.
SheetOffsetDrivenAnimation #
Formerly SheetPositionDrivenAnimation
, this allows creating animations driven by the sheet's offset. It's a special kind of Animation whose value changes (typically from 0 to 1) as the sheet's offset moves between specified startOffset
and endOffset
values (defined using SheetOffset
). This is useful for synchronizing UI changes (like fades, slides, or color changes) with the sheet's movement.
See also:
- sheet_offset_driven_animation.dart for basic usage.
- airbnb_mobile_app.dart, which shows how
SheetOffsetDrivenAnimation
can be used to hide/show UI elements based on the sheet's drag position.
SheetNotification #
A sheet dispatches a SheetNotification when its offset changes. This can be used to observe the offset and other metrics (like min/max offset, viewport size) of a descendant sheet from an ancestor widget using a NotificationListener
.
NotificationListener<SheetNotification>(
onNotification: (notification) {
// Access sheet metrics via notification.metrics (e.g., offset, minOffset, maxOffset)
debugPrint('Current offset: ${notification.metrics.offset}');
return false; // Return true to stop the notification from bubbling up
},
child: SheetViewport( // Required for non-modal sheets
child: Sheet(
// ... sheet configuration
),
),
),
See also:
- SheetDragUpdateNotification, which is dispatched when the sheet is dragged by the user.
- SheetUpdateNotification, which is dispatched when the sheet offset is updated by other means (e.g., animation, controller).
- SheetOverflowNotification, which is dispatched when the user tries to drag the sheet beyond its draggable bounds but the sheet has not changed its offset because its SheetPhysics does not allow it to be.
- NotificationListener, which can be used to listen for the notifications in a subtree.
SheetKeyboardDismissBehavior #
SheetKeyboardDismissBehavior determines when the sheet should dismiss the on-screen keyboard when dragged. This feature is similar to ScrollViewKeyboardDismissBehavior for scrollable widgets. This behavior is configured via the Sheet.keyboardDismissBehavior
property.
Although it is easy to create custom behaviors by implementing the SheetKeyboardDismissBehavior
interface, there are predefined behaviors available as static constants for convenience:
See also:
- tutorial/keyboard_dismiss_behavior.dart for basic usage.
Questions #
If you have any questions, feel free to ask them on the discussions page.
Contributing #
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request