Committed by
GitHub
Merge pull request #36 from jamesblasco/nested_scroll
Nested scroll
Showing
5 changed files
with
93 additions
and
64 deletions
@@ -11,6 +11,7 @@ import 'modals/modal_fit.dart'; | @@ -11,6 +11,7 @@ import 'modals/modal_fit.dart'; | ||
11 | import 'modals/modal_inside_modal.dart'; | 11 | import 'modals/modal_inside_modal.dart'; |
12 | import 'modals/modal_will_scope.dart'; | 12 | import 'modals/modal_will_scope.dart'; |
13 | import 'modals/modal_with_navigator.dart'; | 13 | import 'modals/modal_with_navigator.dart'; |
14 | +import 'modals/modal_with_nested_scroll.dart'; | ||
14 | import 'modals/modal_with_scroll.dart'; | 15 | import 'modals/modal_with_scroll.dart'; |
15 | 16 | ||
16 | import 'examples/cupertino_share.dart'; | 17 | import 'examples/cupertino_share.dart'; |
@@ -219,7 +220,7 @@ class _MyHomePageState extends State<MyHomePage> { | @@ -219,7 +220,7 @@ class _MyHomePageState extends State<MyHomePage> { | ||
219 | scrollController: scrollController), | 220 | scrollController: scrollController), |
220 | )), | 221 | )), |
221 | ListTile( | 222 | ListTile( |
222 | - title: Text('Cupertino Modal with WillPopScope'), | 223 | + title: Text('Modal with WillPopScope'), |
223 | onTap: () => showCupertinoModalBottomSheet( | 224 | onTap: () => showCupertinoModalBottomSheet( |
224 | expand: true, | 225 | expand: true, |
225 | context: context, | 226 | context: context, |
@@ -228,6 +229,15 @@ class _MyHomePageState extends State<MyHomePage> { | @@ -228,6 +229,15 @@ class _MyHomePageState extends State<MyHomePage> { | ||
228 | ModalWillScope( | 229 | ModalWillScope( |
229 | scrollController: scrollController), | 230 | scrollController: scrollController), |
230 | )), | 231 | )), |
232 | + ListTile( | ||
233 | + title: Text('Modal with Nested Scroll'), | ||
234 | + onTap: () => showCupertinoModalBottomSheet( | ||
235 | + expand: true, | ||
236 | + context: context, | ||
237 | + builder: (context, scrollController) => | ||
238 | + NestedScrollModal( | ||
239 | + scrollController: scrollController), | ||
240 | + )), | ||
231 | ], | 241 | ], |
232 | ), | 242 | ), |
233 | ), | 243 | ), |
1 | +import 'package:flutter/cupertino.dart'; | ||
2 | +import 'package:flutter/material.dart'; | ||
3 | + | ||
4 | +class NestedScrollModal extends StatelessWidget { | ||
5 | + final ScrollController scrollController; | ||
6 | + | ||
7 | + const NestedScrollModal({Key key, this.scrollController}) : super(key: key); | ||
8 | + | ||
9 | + @override | ||
10 | + Widget build(BuildContext context) { | ||
11 | + return NestedScrollView( | ||
12 | + | ||
13 | + physics: ScrollPhysics(parent: PageScrollPhysics()), | ||
14 | + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { | ||
15 | + return <Widget>[ | ||
16 | + SliverList( | ||
17 | + delegate: SliverChildListDelegate( | ||
18 | + [ | ||
19 | + Container(height: 300, color: Colors.blue), | ||
20 | + ], | ||
21 | + ), | ||
22 | + ), | ||
23 | + ]; | ||
24 | + }, | ||
25 | + body: ListView.builder( | ||
26 | + controller: scrollController, | ||
27 | + itemBuilder: (context, index) { | ||
28 | + return Container( | ||
29 | + height: 100, | ||
30 | + color: index.isOdd ? Colors.green : Colors.orange, | ||
31 | + ); | ||
32 | + }, | ||
33 | + itemCount: 12, | ||
34 | + )); | ||
35 | + } | ||
36 | +} |
@@ -244,17 +244,19 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> | @@ -244,17 +244,19 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> | ||
244 | DateTime _startTime; | 244 | DateTime _startTime; |
245 | 245 | ||
246 | void _handleScrollUpdate(ScrollNotification notification) { | 246 | void _handleScrollUpdate(ScrollNotification notification) { |
247 | - | ||
248 | final scrollPosition = _scrollController.position; | 247 | final scrollPosition = _scrollController.position; |
249 | 248 | ||
249 | + if (scrollPosition.axis == Axis.horizontal) return; | ||
250 | + | ||
251 | + //Check if scrollController is used | ||
252 | + if (!_scrollController.hasClients) return; | ||
253 | + | ||
250 | final isScrollReversed = scrollPosition.axisDirection == AxisDirection.down; | 254 | final isScrollReversed = scrollPosition.axisDirection == AxisDirection.down; |
251 | final offset = isScrollReversed | 255 | final offset = isScrollReversed |
252 | ? scrollPosition.pixels | 256 | ? scrollPosition.pixels |
253 | : scrollPosition.maxScrollExtent - scrollPosition.pixels; | 257 | : scrollPosition.maxScrollExtent - scrollPosition.pixels; |
254 | 258 | ||
255 | if (offset <= 0) { | 259 | if (offset <= 0) { |
256 | - //Check if scrollController is used | ||
257 | - if (!_scrollController.hasClients) return; | ||
258 | // Check if listener is same from scrollController. | 260 | // Check if listener is same from scrollController. |
259 | // TODO: Improve the way it checks if it the same view controller | 261 | // TODO: Improve the way it checks if it the same view controller |
260 | // Use PrimaryScrollController | 262 | // Use PrimaryScrollController |
@@ -84,6 +84,7 @@ Future<T> showCupertinoModalBottomSheet<T>({ | @@ -84,6 +84,7 @@ Future<T> showCupertinoModalBottomSheet<T>({ | ||
84 | Radius topRadius = _default_top_radius, | 84 | Radius topRadius = _default_top_radius, |
85 | Duration duration, | 85 | Duration duration, |
86 | RouteSettings settings, | 86 | RouteSettings settings, |
87 | + Color transitionBackgroundColor, | ||
87 | }) async { | 88 | }) async { |
88 | assert(context != null); | 89 | assert(context != null); |
89 | assert(builder != null); | 90 | assert(builder != null); |
@@ -121,6 +122,7 @@ Future<T> showCupertinoModalBottomSheet<T>({ | @@ -121,6 +122,7 @@ Future<T> showCupertinoModalBottomSheet<T>({ | ||
121 | previousRouteAnimationCurve: previousRouteAnimationCurve, | 122 | previousRouteAnimationCurve: previousRouteAnimationCurve, |
122 | duration: duration, | 123 | duration: duration, |
123 | settings: settings, | 124 | settings: settings, |
125 | + transitionBackgroundColor: transitionBackgroundColor ?? Colors.black | ||
124 | )); | 126 | )); |
125 | return result; | 127 | return result; |
126 | } | 128 | } |
@@ -129,6 +131,10 @@ class CupertinoModalBottomSheetRoute<T> extends ModalBottomSheetRoute<T> { | @@ -129,6 +131,10 @@ class CupertinoModalBottomSheetRoute<T> extends ModalBottomSheetRoute<T> { | ||
129 | final Radius topRadius; | 131 | final Radius topRadius; |
130 | final Curve previousRouteAnimationCurve; | 132 | final Curve previousRouteAnimationCurve; |
131 | 133 | ||
134 | + // Background color behind all routes | ||
135 | + // Black by default | ||
136 | + final Color transitionBackgroundColor; | ||
137 | + | ||
132 | CupertinoModalBottomSheetRoute({ | 138 | CupertinoModalBottomSheetRoute({ |
133 | ScrollWidgetBuilder builder, | 139 | ScrollWidgetBuilder builder, |
134 | WidgetWithChildBuilder containerBuilder, | 140 | WidgetWithChildBuilder containerBuilder, |
@@ -145,6 +151,7 @@ class CupertinoModalBottomSheetRoute<T> extends ModalBottomSheetRoute<T> { | @@ -145,6 +151,7 @@ class CupertinoModalBottomSheetRoute<T> extends ModalBottomSheetRoute<T> { | ||
145 | @required bool expanded, | 151 | @required bool expanded, |
146 | Duration duration, | 152 | Duration duration, |
147 | RouteSettings settings, | 153 | RouteSettings settings, |
154 | + this.transitionBackgroundColor, | ||
148 | this.topRadius = _default_top_radius, | 155 | this.topRadius = _default_top_radius, |
149 | this.previousRouteAnimationCurve, | 156 | this.previousRouteAnimationCurve, |
150 | }) : assert(expanded != null), | 157 | }) : assert(expanded != null), |
@@ -199,6 +206,7 @@ class CupertinoModalBottomSheetRoute<T> extends ModalBottomSheetRoute<T> { | @@ -199,6 +206,7 @@ class CupertinoModalBottomSheetRoute<T> extends ModalBottomSheetRoute<T> { | ||
199 | body: child, | 206 | body: child, |
200 | animationCurve: previousRouteAnimationCurve, | 207 | animationCurve: previousRouteAnimationCurve, |
201 | topRadius: topRadius, | 208 | topRadius: topRadius, |
209 | + backgroundColor: transitionBackgroundColor ?? Colors.black, | ||
202 | ); | 210 | ); |
203 | } | 211 | } |
204 | } | 212 | } |
@@ -207,6 +215,7 @@ class _CupertinoModalTransition extends StatelessWidget { | @@ -207,6 +215,7 @@ class _CupertinoModalTransition extends StatelessWidget { | ||
207 | final Animation<double> secondaryAnimation; | 215 | final Animation<double> secondaryAnimation; |
208 | final Radius topRadius; | 216 | final Radius topRadius; |
209 | final Curve animationCurve; | 217 | final Curve animationCurve; |
218 | + final Color backgroundColor; | ||
210 | 219 | ||
211 | final Widget body; | 220 | final Widget body; |
212 | 221 | ||
@@ -215,6 +224,7 @@ class _CupertinoModalTransition extends StatelessWidget { | @@ -215,6 +224,7 @@ class _CupertinoModalTransition extends StatelessWidget { | ||
215 | @required this.secondaryAnimation, | 224 | @required this.secondaryAnimation, |
216 | @required this.body, | 225 | @required this.body, |
217 | @required this.topRadius, | 226 | @required this.topRadius, |
227 | + this.backgroundColor = Colors.black, | ||
218 | this.animationCurve, | 228 | this.animationCurve, |
219 | }) : super(key: key); | 229 | }) : super(key: key); |
220 | 230 | ||
@@ -246,7 +256,7 @@ class _CupertinoModalTransition extends StatelessWidget { | @@ -246,7 +256,7 @@ class _CupertinoModalTransition extends StatelessWidget { | ||
246 | : (1 - progress) * startRoundCorner + progress * topRadius.x; | 256 | : (1 - progress) * startRoundCorner + progress * topRadius.x; |
247 | return Stack( | 257 | return Stack( |
248 | children: <Widget>[ | 258 | children: <Widget>[ |
249 | - Container(color: Colors.black), | 259 | + Container(color: backgroundColor), |
250 | Transform.translate( | 260 | Transform.translate( |
251 | offset: Offset(0, yOffset), | 261 | offset: Offset(0, yOffset), |
252 | child: Transform.scale( | 262 | child: Transform.scale( |
@@ -266,6 +276,7 @@ class _CupertinoModalTransition extends StatelessWidget { | @@ -266,6 +276,7 @@ class _CupertinoModalTransition extends StatelessWidget { | ||
266 | 276 | ||
267 | class _CupertinoScaffold extends InheritedWidget { | 277 | class _CupertinoScaffold extends InheritedWidget { |
268 | final AnimationController animation; | 278 | final AnimationController animation; |
279 | + | ||
269 | final Radius topRadius; | 280 | final Radius topRadius; |
270 | 281 | ||
271 | @override | 282 | @override |
@@ -288,10 +299,14 @@ class CupertinoScaffold extends StatefulWidget { | @@ -288,10 +299,14 @@ class CupertinoScaffold extends StatefulWidget { | ||
288 | 299 | ||
289 | final Widget body; | 300 | final Widget body; |
290 | final Radius topRadius; | 301 | final Radius topRadius; |
302 | + final Color transitionBackgroundColor; | ||
291 | 303 | ||
292 | - const CupertinoScaffold( | ||
293 | - {Key key, this.body, this.topRadius = _default_top_radius}) | ||
294 | - : super(key: key); | 304 | + const CupertinoScaffold({ |
305 | + Key key, | ||
306 | + this.body, | ||
307 | + this.topRadius = _default_top_radius, | ||
308 | + this.transitionBackgroundColor = Colors.black, | ||
309 | + }) : super(key: key); | ||
295 | 310 | ||
296 | @override | 311 | @override |
297 | State<StatefulWidget> createState() => _CupertinoScaffoldState(); | 312 | State<StatefulWidget> createState() => _CupertinoScaffoldState(); |
@@ -376,6 +391,7 @@ class _CupertinoScaffoldState extends State<CupertinoScaffold> | @@ -376,6 +391,7 @@ class _CupertinoScaffoldState extends State<CupertinoScaffold> | ||
376 | secondaryAnimation: animationController, | 391 | secondaryAnimation: animationController, |
377 | body: widget.body, | 392 | body: widget.body, |
378 | topRadius: widget.topRadius, | 393 | topRadius: widget.topRadius, |
394 | + backgroundColor: widget.transitionBackgroundColor, | ||
379 | ), | 395 | ), |
380 | ); | 396 | ); |
381 | } | 397 | } |
1 | # Generated by pub | 1 | # Generated by pub |
2 | # See https://dart.dev/tools/pub/glossary#lockfile | 2 | # See https://dart.dev/tools/pub/glossary#lockfile |
3 | packages: | 3 | packages: |
4 | - archive: | ||
5 | - dependency: transitive | ||
6 | - description: | ||
7 | - name: archive | ||
8 | - url: "https://pub.dartlang.org" | ||
9 | - source: hosted | ||
10 | - version: "2.0.13" | ||
11 | - args: | ||
12 | - dependency: transitive | ||
13 | - description: | ||
14 | - name: args | ||
15 | - url: "https://pub.dartlang.org" | ||
16 | - source: hosted | ||
17 | - version: "1.6.0" | ||
18 | async: | 4 | async: |
19 | dependency: transitive | 5 | dependency: transitive |
20 | description: | 6 | description: |
@@ -29,6 +15,13 @@ packages: | @@ -29,6 +15,13 @@ packages: | ||
29 | url: "https://pub.dartlang.org" | 15 | url: "https://pub.dartlang.org" |
30 | source: hosted | 16 | source: hosted |
31 | version: "2.0.0" | 17 | version: "2.0.0" |
18 | + characters: | ||
19 | + dependency: transitive | ||
20 | + description: | ||
21 | + name: characters | ||
22 | + url: "https://pub.dartlang.org" | ||
23 | + source: hosted | ||
24 | + version: "1.0.0" | ||
32 | charcode: | 25 | charcode: |
33 | dependency: transitive | 26 | dependency: transitive |
34 | description: | 27 | description: |
@@ -36,27 +29,27 @@ packages: | @@ -36,27 +29,27 @@ packages: | ||
36 | url: "https://pub.dartlang.org" | 29 | url: "https://pub.dartlang.org" |
37 | source: hosted | 30 | source: hosted |
38 | version: "1.1.3" | 31 | version: "1.1.3" |
39 | - collection: | 32 | + clock: |
40 | dependency: transitive | 33 | dependency: transitive |
41 | description: | 34 | description: |
42 | - name: collection | 35 | + name: clock |
43 | url: "https://pub.dartlang.org" | 36 | url: "https://pub.dartlang.org" |
44 | source: hosted | 37 | source: hosted |
45 | - version: "1.14.12" | ||
46 | - convert: | 38 | + version: "1.0.1" |
39 | + collection: | ||
47 | dependency: transitive | 40 | dependency: transitive |
48 | description: | 41 | description: |
49 | - name: convert | 42 | + name: collection |
50 | url: "https://pub.dartlang.org" | 43 | url: "https://pub.dartlang.org" |
51 | source: hosted | 44 | source: hosted |
52 | - version: "2.1.1" | ||
53 | - crypto: | 45 | + version: "1.14.13" |
46 | + fake_async: | ||
54 | dependency: transitive | 47 | dependency: transitive |
55 | description: | 48 | description: |
56 | - name: crypto | 49 | + name: fake_async |
57 | url: "https://pub.dartlang.org" | 50 | url: "https://pub.dartlang.org" |
58 | source: hosted | 51 | source: hosted |
59 | - version: "2.1.4" | 52 | + version: "1.1.0" |
60 | flutter: | 53 | flutter: |
61 | dependency: "direct main" | 54 | dependency: "direct main" |
62 | description: flutter | 55 | description: flutter |
@@ -67,20 +60,13 @@ packages: | @@ -67,20 +60,13 @@ packages: | ||
67 | description: flutter | 60 | description: flutter |
68 | source: sdk | 61 | source: sdk |
69 | version: "0.0.0" | 62 | version: "0.0.0" |
70 | - image: | ||
71 | - dependency: transitive | ||
72 | - description: | ||
73 | - name: image | ||
74 | - url: "https://pub.dartlang.org" | ||
75 | - source: hosted | ||
76 | - version: "2.1.12" | ||
77 | matcher: | 63 | matcher: |
78 | dependency: transitive | 64 | dependency: transitive |
79 | description: | 65 | description: |
80 | name: matcher | 66 | name: matcher |
81 | url: "https://pub.dartlang.org" | 67 | url: "https://pub.dartlang.org" |
82 | source: hosted | 68 | source: hosted |
83 | - version: "0.12.6" | 69 | + version: "0.12.8" |
84 | meta: | 70 | meta: |
85 | dependency: transitive | 71 | dependency: transitive |
86 | description: | 72 | description: |
@@ -94,28 +80,14 @@ packages: | @@ -94,28 +80,14 @@ packages: | ||
94 | name: path | 80 | name: path |
95 | url: "https://pub.dartlang.org" | 81 | url: "https://pub.dartlang.org" |
96 | source: hosted | 82 | source: hosted |
97 | - version: "1.6.4" | 83 | + version: "1.7.0" |
98 | pedantic: | 84 | pedantic: |
99 | dependency: "direct dev" | 85 | dependency: "direct dev" |
100 | description: | 86 | description: |
101 | name: pedantic | 87 | name: pedantic |
102 | url: "https://pub.dartlang.org" | 88 | url: "https://pub.dartlang.org" |
103 | source: hosted | 89 | source: hosted |
104 | - version: "1.8.0+1" | ||
105 | - petitparser: | ||
106 | - dependency: transitive | ||
107 | - description: | ||
108 | - name: petitparser | ||
109 | - url: "https://pub.dartlang.org" | ||
110 | - source: hosted | ||
111 | - version: "2.4.0" | ||
112 | - quiver: | ||
113 | - dependency: transitive | ||
114 | - description: | ||
115 | - name: quiver | ||
116 | - url: "https://pub.dartlang.org" | ||
117 | - source: hosted | ||
118 | - version: "2.1.3" | 90 | + version: "1.9.0" |
119 | sky_engine: | 91 | sky_engine: |
120 | dependency: transitive | 92 | dependency: transitive |
121 | description: flutter | 93 | description: flutter |
@@ -162,7 +134,7 @@ packages: | @@ -162,7 +134,7 @@ packages: | ||
162 | name: test_api | 134 | name: test_api |
163 | url: "https://pub.dartlang.org" | 135 | url: "https://pub.dartlang.org" |
164 | source: hosted | 136 | source: hosted |
165 | - version: "0.2.15" | 137 | + version: "0.2.17" |
166 | typed_data: | 138 | typed_data: |
167 | dependency: transitive | 139 | dependency: transitive |
168 | description: | 140 | description: |
@@ -177,13 +149,6 @@ packages: | @@ -177,13 +149,6 @@ packages: | ||
177 | url: "https://pub.dartlang.org" | 149 | url: "https://pub.dartlang.org" |
178 | source: hosted | 150 | source: hosted |
179 | version: "2.0.8" | 151 | version: "2.0.8" |
180 | - xml: | ||
181 | - dependency: transitive | ||
182 | - description: | ||
183 | - name: xml | ||
184 | - url: "https://pub.dartlang.org" | ||
185 | - source: hosted | ||
186 | - version: "3.6.1" | ||
187 | sdks: | 152 | sdks: |
188 | - dart: ">=2.6.0 <3.0.0" | 153 | + dart: ">=2.9.0-14.0.dev <3.0.0" |
189 | flutter: ">=1.12.0 <2.0.0" | 154 | flutter: ">=1.12.0 <2.0.0" |
-
Please register or login to post a comment