diff --git a/.vscode/launch.json b/.vscode/launch.json index 71aca65c..19ecfa80 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -74,6 +74,13 @@ "program": "lib/tutorial/sheet_content_scaffold.dart", "cwd": "./cookbook" }, + { + "name": "Bottom Bar Visibility", + "request": "launch", + "type": "dart", + "program": "lib/tutorial/bottom_bar_visibility.dart", + "cwd": "./cookbook" + }, { "name": "Sheet Controller", "request": "launch", diff --git a/cookbook/lib/tutorial/bottom_bar_visibility.dart b/cookbook/lib/tutorial/bottom_bar_visibility.dart new file mode 100644 index 00000000..a3645ce7 --- /dev/null +++ b/cookbook/lib/tutorial/bottom_bar_visibility.dart @@ -0,0 +1,183 @@ +import 'package:flutter/material.dart'; +import 'package:smooth_sheets/smooth_sheets.dart'; + +void main() { + runApp(const _BottomBarVisibilityExample()); +} + +class _BottomBarVisibilityExample extends StatelessWidget { + const _BottomBarVisibilityExample(); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: _ExampleHome(), + ); + } +} + +enum _BottomBarVisibilityType { + fixed( + name: 'FixedBottomBarVisibility', + description: 'The bottom bar is fixed at the bottommost of the sheet.', + ), + sticky( + name: 'StickyBottomBarVisibility', + description: + 'The bottom bar is always visible regardless of the sheet position.', + ), + conditionalSticky( + name: 'ConditionalStickyBottomBarVisibility', + description: + 'The bottom bar is visible only when a certain condition is met.', + ); + + final String name; + final String description; + + const _BottomBarVisibilityType({ + required this.name, + required this.description, + }); +} + +class _ExampleHome extends StatefulWidget { + const _ExampleHome(); + + @override + State<_ExampleHome> createState() => _ExampleHomeState(); +} + +class _ExampleHomeState extends State<_ExampleHome> { + _BottomBarVisibilityType selectedVisibilityType = + _BottomBarVisibilityType.sticky; + + @override + Widget build(BuildContext context) { + final options = [ + for (final type in _BottomBarVisibilityType.values) + RadioListTile( + title: Text(type.name), + subtitle: Text(type.description), + value: type, + groupValue: selectedVisibilityType, + contentPadding: const EdgeInsets.only(left: 24, right: 16), + controlAffinity: ListTileControlAffinity.trailing, + onChanged: (value) => setState(() { + selectedVisibilityType = value!; + }), + ), + ]; + + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ListTile( + title: Text('BottomBarVisibility'), + subtitle: Text( + 'Controls the visibility of the bottom bar based on the sheet position. ' + "Intended to be used as the 'SheetContentScaffold.bottomBar'.", + ), + ), + ...options, + const SizedBox(height: 100), + ], + ), + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, + floatingActionButton: FloatingActionButton.extended( + label: const Text('Show sheet'), + onPressed: () => showExampleSheet(context), + ), + ); + } + + void showExampleSheet(BuildContext context) { + Navigator.push( + context, + ModalSheetRoute( + builder: (context) => _ExampleSheet( + visibilityType: selectedVisibilityType, + ), + ), + ); + } +} + +class _ExampleSheet extends StatelessWidget { + const _ExampleSheet({ + required this.visibilityType, + }); + + final _BottomBarVisibilityType visibilityType; + + @override + Widget build(BuildContext context) { + final bottomBar = BottomAppBar( + child: Row( + children: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.menu), + ), + const Spacer(), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.more_vert), + ), + ], + ), + ); + + const minSize = Extent.proportional(0.3); + const halfSize = Extent.proportional(0.5); + const fullSize = Extent.proportional(1); + + final multiStopPhysics = StretchingSheetPhysics( + parent: SnappingSheetPhysics( + snappingBehavior: SnapToNearest( + snapTo: const [minSize, halfSize, fullSize], + ), + ), + ); + + return SafeArea( + bottom: false, + child: DraggableSheet( + minExtent: minSize, + initialExtent: halfSize, + physics: multiStopPhysics, + child: SheetContentScaffold( + appBar: AppBar(), + body: const SizedBox.expand(), + bottomBar: switch (visibilityType) { + _BottomBarVisibilityType.fixed => + FixedBottomBarVisibility(child: bottomBar), + _BottomBarVisibilityType.sticky => + StickyBottomBarVisibility(child: bottomBar), + _BottomBarVisibilityType.conditionalSticky => + ConditionalStickyBottomBarVisibility( + // This callback is called whenever the sheet metrics changes, + // and returning true keeps the bottom bar visible. + getIsVisible: (metrics) { + // The bottom bar is visible when at least 50% of the sheet is visible. + return metrics.pixels >= + const Extent.proportional(0.5) + .resolve(metrics.contentDimensions); + }, + child: bottomBar, + ), + }, + // Add the following 3 lines to keep the bottom bar visible when the keyboard is open. + // resizeBehavior: const ResizeScaffoldBehavior.avoidBottomInset( + // maintainBottomBar: true, + // ), + ), + ), + ); + } +} diff --git a/package/README.md b/package/README.md index d353956f..a7a110c8 100644 --- a/package/README.md +++ b/package/README.md @@ -265,9 +265,10 @@ A special kind of [Scaffold](https://api.flutter.dev/flutter/material/Scaffold-c See also: -- [tutorial/sheet_content_scaffold.dart](https://github.com/fujidaiti/smooth_sheets/blob/main/cookbook/lib/tutorial/sheet_content_scaffold.dart), which shows the basic usage of this widget. - [SheetContentScaffold](https://pub.dev/documentation/smooth_sheets/latest/smooth_sheets/SheetContentScaffold-class.html), the API documentation. - [BottomBarVisibility](https://pub.dev/documentation/smooth_sheets/latest/smooth_sheets/BottomBarVisibility-class.html), which can be used to control the visibility of the bottom bar based on the sheet position. +- [tutorial/sheet_content_scaffold.dart](https://github.com/fujidaiti/smooth_sheets/blob/main/cookbook/lib/tutorial/sheet_content_scaffold.dart), which shows the basic usage of SheetContentScaffold. +- [tutorial/bottom_bar_visibility.dart](https://github.com/fujidaiti/smooth_sheets/blob/main/cookbook/lib/tutorial/bottom_bar_visibility.dart), which shows the basic usage of BottomBarVisibility widgets.