Jaime Blasco

Fix scroll handling for physics that not overflow as ClampingScrollPhysics

@@ -10,11 +10,7 @@ @@ -10,11 +10,7 @@
10 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 10 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 212D1E304840672EFB9BFFA7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D52A2E75CF34C7E6DC549F4 /* Pods_Runner.framework */; }; 11 212D1E304840672EFB9BFFA7 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D52A2E75CF34C7E6DC549F4 /* Pods_Runner.framework */; };
12 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13 - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };  
14 - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };  
15 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
16 - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };  
17 - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };  
18 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
19 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
20 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -27,8 +23,6 @@ @@ -27,8 +23,6 @@
27 dstPath = ""; 23 dstPath = "";
28 dstSubfolderSpec = 10; 24 dstSubfolderSpec = 10;
29 files = ( 25 files = (
30 - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,  
31 - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,  
32 ); 26 );
33 name = "Embed Frameworks"; 27 name = "Embed Frameworks";
34 runOnlyForDeploymentPostprocessing = 0; 28 runOnlyForDeploymentPostprocessing = 0;
@@ -40,14 +34,12 @@ @@ -40,14 +34,12 @@
40 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 34 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
41 248080BB287D735D5E630360 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; 35 248080BB287D735D5E630360 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
42 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 36 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
43 - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };  
44 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 37 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
45 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 38 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
46 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 39 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
47 8D52A2E75CF34C7E6DC549F4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 40 8D52A2E75CF34C7E6DC549F4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
48 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 41 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
49 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 42 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
50 - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };  
51 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
52 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 44 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
53 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 45 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -62,8 +54,6 @@ @@ -62,8 +54,6 @@
62 isa = PBXFrameworksBuildPhase; 54 isa = PBXFrameworksBuildPhase;
63 buildActionMask = 2147483647; 55 buildActionMask = 2147483647;
64 files = ( 56 files = (
65 - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,  
66 - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,  
67 212D1E304840672EFB9BFFA7 /* Pods_Runner.framework in Frameworks */, 57 212D1E304840672EFB9BFFA7 /* Pods_Runner.framework in Frameworks */,
68 ); 58 );
69 runOnlyForDeploymentPostprocessing = 0; 59 runOnlyForDeploymentPostprocessing = 0;
@@ -85,9 +75,7 @@ @@ -85,9 +75,7 @@
85 9740EEB11CF90186004384FC /* Flutter */ = { 75 9740EEB11CF90186004384FC /* Flutter */ = {
86 isa = PBXGroup; 76 isa = PBXGroup;
87 children = ( 77 children = (
88 - 3B80C3931E831B6300D905FE /* App.framework */,  
89 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 78 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
90 - 9740EEBA1CF902C7004384FC /* Flutter.framework */,  
91 9740EEB21CF90195004384FC /* Debug.xcconfig */, 79 9740EEB21CF90195004384FC /* Debug.xcconfig */,
92 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 80 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
93 9740EEB31CF90195004384FC /* Generated.xcconfig */, 81 9740EEB31CF90195004384FC /* Generated.xcconfig */,
@@ -252,7 +240,7 @@ @@ -252,7 +240,7 @@
252 ); 240 );
253 runOnlyForDeploymentPostprocessing = 0; 241 runOnlyForDeploymentPostprocessing = 0;
254 shellPath = /bin/sh; 242 shellPath = /bin/sh;
255 - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 243 + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
256 }; 244 };
257 87338F8232AE1406F5B9308C /* [CP] Embed Pods Frameworks */ = { 245 87338F8232AE1406F5B9308C /* [CP] Embed Pods Frameworks */ = {
258 isa = PBXShellScriptBuildPhase; 246 isa = PBXShellScriptBuildPhase;
@@ -179,7 +179,6 @@ class _MyHomePageState extends State<MyHomePage> { @@ -179,7 +179,6 @@ class _MyHomePageState extends State<MyHomePage> {
179 expand: true, 179 expand: true,
180 context: context, 180 context: context,
181 backgroundColor: Colors.transparent, 181 backgroundColor: Colors.transparent,
182 - animationCurve: Curves.easeInExpo,  
183 builder: (context, scrollController) => 182 builder: (context, scrollController) =>
184 ModalInsideModal( 183 ModalInsideModal(
185 scrollController: scrollController), 184 scrollController: scrollController),
@@ -18,7 +18,7 @@ class ModalInsideModal extends StatelessWidget { @@ -18,7 +18,7 @@ class ModalInsideModal extends StatelessWidget {
18 child: ListView( 18 child: ListView(
19 shrinkWrap: true, 19 shrinkWrap: true,
20 controller: scrollController, 20 controller: scrollController,
21 - physics: BouncingScrollPhysics(), 21 + physics: ClampingScrollPhysics(),
22 children: ListTile.divideTiles( 22 children: ListTile.divideTiles(
23 context: context, 23 context: context,
24 tiles: List.generate( 24 tiles: List.generate(
@@ -240,14 +240,30 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> @@ -240,14 +240,30 @@ class _ModalBottomSheetState extends State<ModalBottomSheet>
240 240
241 void _handleScrollUpdate(ScrollNotification notification) { 241 void _handleScrollUpdate(ScrollNotification notification) {
242 if (notification.metrics.pixels <= notification.metrics.minScrollExtent) { 242 if (notification.metrics.pixels <= notification.metrics.minScrollExtent) {
243 - //Check if listener is same from scrollController  
244 if (!_scrollController.hasClients) return; 243 if (!_scrollController.hasClients) return;
245 244
246 - if (_scrollController.position.pixels != notification.metrics.pixels) { 245 + // Check if listener is same from scrollController.
  246 + // TODO: Improve the way it checks if it the same view controller
  247 + // Use PrimaryScrollController
  248 + if (_scrollController.position.pixels != notification.metrics.pixels &&
  249 + !(_scrollController.position.pixels == 0 &&
  250 + notification.metrics.pixels >= 0)) {
247 return; 251 return;
248 } 252 }
  253 + // Clamping Scroll Physics end with a ScrollEndNotification with a DragEndDetail class
  254 + // while Bouncing Scroll Physics or other physics that Overflow don't return a drag end info
  255 +
  256 + // We use the velocity from DragEndDetail in case it is available
  257 + if (notification is ScrollEndNotification &&
  258 + notification.dragDetails != null) {
  259 + _handleDragEnd(notification.dragDetails.primaryVelocity);
  260 + _velocityTracker = null;
  261 + _startTime = null;
  262 + return;
  263 + }
  264 + // Otherwise the calculate the velocity with a VelocityTracker
249 DragUpdateDetails dragDetails; 265 DragUpdateDetails dragDetails;
250 - if (notification is ScrollStartNotification) { 266 + if (_velocityTracker == null) {
251 _velocityTracker = VelocityTracker(); 267 _velocityTracker = VelocityTracker();
252 _startTime = DateTime.now(); 268 _startTime = DateTime.now();
253 } 269 }
@@ -259,11 +275,13 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> @@ -259,11 +275,13 @@ class _ModalBottomSheetState extends State<ModalBottomSheet>
259 } 275 }
260 if (dragDetails != null) { 276 if (dragDetails != null) {
261 final duration = _startTime.difference(DateTime.now()); 277 final duration = _startTime.difference(DateTime.now());
262 - final offset = Offset(0, _scrollController.offset); 278 + final offset = Offset(0, notification.metrics.pixels);
263 _velocityTracker.addPosition(duration, offset); 279 _velocityTracker.addPosition(duration, offset);
264 _handleDragUpdate(dragDetails.primaryDelta); 280 _handleDragUpdate(dragDetails.primaryDelta);
265 } else if (isDragging) { 281 } else if (isDragging) {
266 final velocity = _velocityTracker.getVelocity().pixelsPerSecond.dy; 282 final velocity = _velocityTracker.getVelocity().pixelsPerSecond.dy;
  283 + _velocityTracker = null;
  284 + _startTime = null;
267 _handleDragEnd(velocity); 285 _handleDragEnd(velocity);
268 } 286 }
269 } 287 }