1+ import 'package:collection/collection.dart' ;
12import 'package:ensemble/framework/action.dart' ;
23import 'package:ensemble/framework/data_context.dart' ;
34import 'package:ensemble/framework/error_handling.dart' ;
@@ -85,6 +86,14 @@ class ShowBottomSheetAction extends EnsembleAction {
8586 min: 0 ,
8687 max: 1 );
8788
89+ bool isSnap (scopeManager) =>
90+ Utils .optionalBool (
91+ eval (payload["scrollOptions" ]? ["snap" ], scopeManager)) ??
92+ false ;
93+
94+ List <double >? additionalSnaps (scopeManager) => Utils .getList <double >(
95+ eval (payload["scrollOptions" ]? ["additionalViewportSnaps" ], scopeManager));
96+
8897 @override
8998 Future <dynamic > execute (BuildContext context, ScopeManager scopeManager) {
9099 if (body != null ) {
@@ -140,6 +149,12 @@ class ShowBottomSheetAction extends EnsembleAction {
140149 initialViewport = (minViewport + maxViewport) / 2.0 ;
141150 }
142151
152+ bool useSnap = isSnap (scopeManager);
153+ List <double >? snaps = additionalSnaps (scopeManager)
154+ ? .where ((item) => item > minViewport && item < maxViewport)
155+ .toList ();
156+ snaps? .sort ();
157+
143158 // On platforms with a mouse (Web/desktop), there is no min/maxViewport due to platform consistency,
144159 // so the height will be fixed to initialViewport, and content will just scroll within it.
145160 // https://docs.flutter.dev/release/breaking-changes/default-scroll-behavior-drag
@@ -148,6 +163,8 @@ class ShowBottomSheetAction extends EnsembleAction {
148163 minChildSize: minViewport,
149164 maxChildSize: maxViewport,
150165 initialChildSize: initialViewport,
166+ snap: useSnap,
167+ snapSizes: useSnap ? snaps : null ,
151168 builder: (context, scrollController) =>
152169 buildRootContainer (scopeManager, context,
153170 child: SingleChildScrollView (
0 commit comments