Temporary replace of PrimaryScrollController
This issue would be solved first https://github.com/flutter/flutter/issues/64236
Showing
11 changed files
with
94 additions
and
29 deletions
@@ -92,7 +92,7 @@ class PhotoShareBottomSheet extends StatelessWidget { | @@ -92,7 +92,7 @@ class PhotoShareBottomSheet extends StatelessWidget { | ||
92 | appBar: appBar(context), | 92 | appBar: appBar(context), |
93 | body: CustomScrollView( | 93 | body: CustomScrollView( |
94 | physics: ClampingScrollPhysics(), | 94 | physics: ClampingScrollPhysics(), |
95 | - primary: true, | 95 | + controller: ModalScrollController.of(context), |
96 | slivers: <Widget>[ | 96 | slivers: <Widget>[ |
97 | SliverSafeArea( | 97 | SliverSafeArea( |
98 | bottom: false, | 98 | bottom: false, |
1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; |
2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
3 | +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; | ||
3 | 4 | ||
4 | class ComplexModal extends StatelessWidget { | 5 | class ComplexModal extends StatelessWidget { |
5 | - | ||
6 | - | ||
7 | const ComplexModal({Key key}) : super(key: key); | 6 | const ComplexModal({Key key}) : super(key: key); |
8 | 7 | ||
9 | @override | 8 | @override |
10 | Widget build(BuildContext context) { | 9 | Widget build(BuildContext context) { |
11 | - final scrollController = PrimaryScrollController.of(context); | ||
12 | return Material( | 10 | return Material( |
13 | child: WillPopScope( | 11 | child: WillPopScope( |
14 | onWillPop: () async { | 12 | onWillPop: () async { |
@@ -47,8 +45,7 @@ class ComplexModal extends StatelessWidget { | @@ -47,8 +45,7 @@ class ComplexModal extends StatelessWidget { | ||
47 | bottom: false, | 45 | bottom: false, |
48 | child: ListView( | 46 | child: ListView( |
49 | shrinkWrap: true, | 47 | shrinkWrap: true, |
50 | - | ||
51 | - controller: scrollController, | 48 | + controller: ModalScrollController.of(context), |
52 | children: ListTile.divideTiles( | 49 | children: ListTile.divideTiles( |
53 | context: context, | 50 | context: context, |
54 | tiles: List.generate( | 51 | tiles: List.generate( |
@@ -9,7 +9,6 @@ class ModalInsideModal extends StatelessWidget { | @@ -9,7 +9,6 @@ class ModalInsideModal extends StatelessWidget { | ||
9 | 9 | ||
10 | @override | 10 | @override |
11 | Widget build(BuildContext context) { | 11 | Widget build(BuildContext context) { |
12 | - final scrollController = PrimaryScrollController.of(context); | ||
13 | return Material( | 12 | return Material( |
14 | child: CupertinoPageScaffold( | 13 | child: CupertinoPageScaffold( |
15 | navigationBar: CupertinoNavigationBar( | 14 | navigationBar: CupertinoNavigationBar( |
@@ -19,7 +18,7 @@ class ModalInsideModal extends StatelessWidget { | @@ -19,7 +18,7 @@ class ModalInsideModal extends StatelessWidget { | ||
19 | child: ListView( | 18 | child: ListView( |
20 | reverse: reverse, | 19 | reverse: reverse, |
21 | shrinkWrap: true, | 20 | shrinkWrap: true, |
22 | - controller: scrollController, | 21 | + controller: ModalScrollController.of(context), |
23 | physics: ClampingScrollPhysics(), | 22 | physics: ClampingScrollPhysics(), |
24 | children: ListTile.divideTiles( | 23 | children: ListTile.divideTiles( |
25 | context: context, | 24 | context: context, |
1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; |
2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
3 | +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; | ||
3 | 4 | ||
4 | class ModalWithNavigator extends StatelessWidget { | 5 | class ModalWithNavigator extends StatelessWidget { |
5 | 6 | ||
@@ -8,7 +9,6 @@ class ModalWithNavigator extends StatelessWidget { | @@ -8,7 +9,6 @@ class ModalWithNavigator extends StatelessWidget { | ||
8 | 9 | ||
9 | @override | 10 | @override |
10 | Widget build(BuildContext context) { | 11 | Widget build(BuildContext context) { |
11 | - final scrollController = PrimaryScrollController.of(context); | ||
12 | return Material( | 12 | return Material( |
13 | child: Navigator( | 13 | child: Navigator( |
14 | onGenerateRoute: (_) => MaterialPageRoute( | 14 | onGenerateRoute: (_) => MaterialPageRoute( |
@@ -20,7 +20,7 @@ class ModalWithNavigator extends StatelessWidget { | @@ -20,7 +20,7 @@ class ModalWithNavigator extends StatelessWidget { | ||
20 | bottom: false, | 20 | bottom: false, |
21 | child: ListView( | 21 | child: ListView( |
22 | shrinkWrap: true, | 22 | shrinkWrap: true, |
23 | - controller: scrollController, | 23 | + controller: ModalScrollController.of(context), |
24 | children: ListTile.divideTiles( | 24 | children: ListTile.divideTiles( |
25 | context: context, | 25 | context: context, |
26 | tiles: List.generate( | 26 | tiles: List.generate( |
1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; |
2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
3 | +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; | ||
3 | 4 | ||
4 | class NestedScrollModal extends StatelessWidget { | 5 | class NestedScrollModal extends StatelessWidget { |
5 | const NestedScrollModal({Key key}) : super(key: key); | 6 | const NestedScrollModal({Key key}) : super(key: key); |
@@ -7,7 +8,6 @@ class NestedScrollModal extends StatelessWidget { | @@ -7,7 +8,6 @@ class NestedScrollModal extends StatelessWidget { | ||
7 | 8 | ||
8 | @override | 9 | @override |
9 | Widget build(BuildContext context) { | 10 | Widget build(BuildContext context) { |
10 | - final scrollController = PrimaryScrollController.of(context); | ||
11 | return NestedScrollView( | 11 | return NestedScrollView( |
12 | controller: ScrollController(), | 12 | controller: ScrollController(), |
13 | physics: ScrollPhysics(parent: PageScrollPhysics()), | 13 | physics: ScrollPhysics(parent: PageScrollPhysics()), |
@@ -23,7 +23,7 @@ class NestedScrollModal extends StatelessWidget { | @@ -23,7 +23,7 @@ class NestedScrollModal extends StatelessWidget { | ||
23 | ]; | 23 | ]; |
24 | }, | 24 | }, |
25 | body: ListView.builder( | 25 | body: ListView.builder( |
26 | - controller: scrollController, | 26 | + controller: ModalScrollController.of(context), |
27 | itemBuilder: (context, index) { | 27 | itemBuilder: (context, index) { |
28 | return Container( | 28 | return Container( |
29 | height: 100, | 29 | height: 100, |
1 | import 'package:flutter/cupertino.dart'; | 1 | import 'package:flutter/cupertino.dart'; |
2 | import 'package:flutter/material.dart'; | 2 | import 'package:flutter/material.dart'; |
3 | +import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; | ||
3 | 4 | ||
4 | class ModalWithScroll extends StatelessWidget { | 5 | class ModalWithScroll extends StatelessWidget { |
5 | const ModalWithScroll({Key key}) : super(key: key); | 6 | const ModalWithScroll({Key key}) : super(key: key); |
6 | 7 | ||
7 | @override | 8 | @override |
8 | Widget build(BuildContext context) { | 9 | Widget build(BuildContext context) { |
9 | - final scrollController = PrimaryScrollController.of(context); | 10 | + |
10 | return Material( | 11 | return Material( |
11 | child: CupertinoPageScaffold( | 12 | child: CupertinoPageScaffold( |
12 | navigationBar: CupertinoNavigationBar( | 13 | navigationBar: CupertinoNavigationBar( |
@@ -15,7 +16,7 @@ class ModalWithScroll extends StatelessWidget { | @@ -15,7 +16,7 @@ class ModalWithScroll extends StatelessWidget { | ||
15 | bottom: false, | 16 | bottom: false, |
16 | child: ListView( | 17 | child: ListView( |
17 | shrinkWrap: true, | 18 | shrinkWrap: true, |
18 | - controller: scrollController, | 19 | + controller: ModalScrollController.of(context), |
19 | children: ListTile.divideTiles( | 20 | children: ListTile.divideTiles( |
20 | context: context, | 21 | context: context, |
21 | tiles: List.generate( | 22 | tiles: List.generate( |
@@ -4,3 +4,4 @@ export 'src/material_with_modal_page_route.dart'; | @@ -4,3 +4,4 @@ export 'src/material_with_modal_page_route.dart'; | ||
4 | export 'src/bottom_sheets/cupertino_bottom_sheet.dart'; | 4 | export 'src/bottom_sheets/cupertino_bottom_sheet.dart'; |
5 | export 'src/bottom_sheets/material_bottom_sheet.dart'; | 5 | export 'src/bottom_sheets/material_bottom_sheet.dart'; |
6 | export 'src/bottom_sheets/bar_bottom_sheet.dart'; | 6 | export 'src/bottom_sheets/bar_bottom_sheet.dart'; |
7 | +export 'src/utils/modal_scroll_controller.dart'; |
@@ -10,7 +10,7 @@ import 'package:flutter/gestures.dart'; | @@ -10,7 +10,7 @@ import 'package:flutter/gestures.dart'; | ||
10 | import 'package:flutter/material.dart'; | 10 | import 'package:flutter/material.dart'; |
11 | import 'package:flutter/scheduler.dart'; | 11 | import 'package:flutter/scheduler.dart'; |
12 | import 'package:flutter/widgets.dart'; | 12 | import 'package:flutter/widgets.dart'; |
13 | -import 'package:modal_bottom_sheet/src/utils/primary_scroll_status_bar.dart'; | 13 | +import 'package:modal_bottom_sheet/src/utils/scroll_to_top_status_bar.dart'; |
14 | 14 | ||
15 | import 'package:modal_bottom_sheet/src/utils/bottom_sheet_suspended_curve.dart'; | 15 | import 'package:modal_bottom_sheet/src/utils/bottom_sheet_suspended_curve.dart'; |
16 | 16 | ||
@@ -282,7 +282,7 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> | @@ -282,7 +282,7 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> | ||
282 | return; | 282 | return; |
283 | } | 283 | } |
284 | 284 | ||
285 | -// Otherwise the calculate the velocity with a VelocityTracker | 285 | + // Otherwise the calculate the velocity with a VelocityTracker |
286 | if (_velocityTracker == null) { | 286 | if (_velocityTracker == null) { |
287 | _velocityTracker = VelocityTracker(); | 287 | _velocityTracker = VelocityTracker(); |
288 | _startTime = DateTime.now(); | 288 | _startTime = DateTime.now(); |
@@ -385,7 +385,10 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> | @@ -385,7 +385,10 @@ class _ModalBottomSheetState extends State<ModalBottomSheet> | ||
385 | child: RepaintBoundary(child: child), | 385 | child: RepaintBoundary(child: child), |
386 | ); | 386 | ); |
387 | 387 | ||
388 | - return PrimaryScrollStatusBarHandler(child: child); | 388 | + return ScrollToTopStatusBarHandler( |
389 | + child: child, | ||
390 | + scrollController: _scrollController, | ||
391 | + ); | ||
389 | } | 392 | } |
390 | } | 393 | } |
391 | 394 |
@@ -3,6 +3,7 @@ import 'dart:async'; | @@ -3,6 +3,7 @@ import 'dart:async'; | ||
3 | import 'package:flutter/cupertino.dart'; | 3 | import 'package:flutter/cupertino.dart'; |
4 | import 'package:flutter/foundation.dart'; | 4 | import 'package:flutter/foundation.dart'; |
5 | import 'package:flutter/material.dart'; | 5 | import 'package:flutter/material.dart'; |
6 | +import 'package:modal_bottom_sheet/src/utils/modal_scroll_controller.dart'; | ||
6 | 7 | ||
7 | import '../modal_bottom_sheet.dart'; | 8 | import '../modal_bottom_sheet.dart'; |
8 | 9 | ||
@@ -74,10 +75,10 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { | @@ -74,10 +75,10 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { | ||
74 | @override | 75 | @override |
75 | Widget build(BuildContext context) { | 76 | Widget build(BuildContext context) { |
76 | assert(debugCheckHasMediaQuery(context)); | 77 | assert(debugCheckHasMediaQuery(context)); |
77 | - | ||
78 | - return PrimaryScrollController( | ||
79 | - controller: PrimaryScrollController.of(context) ?? | ||
80 | - (_scrollController ??= ScrollController()), | 78 | + final scrollController = PrimaryScrollController.of(context) ?? |
79 | + (_scrollController ??= ScrollController()); | ||
80 | + return ModalScrollController( | ||
81 | + controller: scrollController, | ||
81 | child: Builder( | 82 | child: Builder( |
82 | builder: (context) => AnimatedBuilder( | 83 | builder: (context) => AnimatedBuilder( |
83 | animation: widget.route._animationController, | 84 | animation: widget.route._animationController, |
@@ -107,7 +108,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { | @@ -107,7 +108,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { | ||
107 | child: child, | 108 | child: child, |
108 | enableDrag: widget.enableDrag, | 109 | enableDrag: widget.enableDrag, |
109 | bounce: widget.bounce, | 110 | bounce: widget.bounce, |
110 | - scrollController: PrimaryScrollController.of(context), | 111 | + scrollController: scrollController, |
111 | animationCurve: widget.animationCurve, | 112 | animationCurve: widget.animationCurve, |
112 | ), | 113 | ), |
113 | ); | 114 | ); |
lib/src/utils/modal_scroll_controller.dart
0 → 100644
1 | +import 'package:flutter/rendering.dart'; | ||
2 | +import 'package:flutter/widgets.dart'; | ||
3 | + | ||
4 | +/// Associates a [ScrollController] with a subtree. | ||
5 | +/// | ||
6 | +/// This mechanism can be used to provide default behavior for scroll views in a | ||
7 | +/// subtree inside a modal bottom sheet. | ||
8 | +/// | ||
9 | +/// We want to remove this and use [PrimaryScrollController]. | ||
10 | +/// This issue should be solved first https://github.com/flutter/flutter/issues/64236 | ||
11 | +/// | ||
12 | +/// See [PrimaryScrollController] | ||
13 | +class ModalScrollController extends InheritedWidget { | ||
14 | + /// Creates a widget that associates a [ScrollController] with a subtree. | ||
15 | + ModalScrollController({ | ||
16 | + Key key, | ||
17 | + @required this.controller, | ||
18 | + @required Widget child, | ||
19 | + }) : assert(controller != null), | ||
20 | + super( | ||
21 | + key: key, | ||
22 | + child: PrimaryScrollController( | ||
23 | + controller: controller, | ||
24 | + child: child, | ||
25 | + ), | ||
26 | + ); | ||
27 | + | ||
28 | + /// The [ScrollController] associated with the subtree. | ||
29 | + /// | ||
30 | + /// See also: | ||
31 | + /// | ||
32 | + /// * [ScrollView.controller], which discusses the purpose of specifying a | ||
33 | + /// scroll controller. | ||
34 | + final ScrollController controller; | ||
35 | + | ||
36 | + /// Returns the [ScrollController] most closely associated with the given | ||
37 | + /// context. | ||
38 | + /// | ||
39 | + /// Returns null if there is no [ScrollController] associated with the given | ||
40 | + /// context. | ||
41 | + static ScrollController of(BuildContext context) { | ||
42 | + final ModalScrollController result = | ||
43 | + context.dependOnInheritedWidgetOfExactType<ModalScrollController>(); | ||
44 | + return result?.controller; | ||
45 | + } | ||
46 | + | ||
47 | + @override | ||
48 | + bool updateShouldNotify(ModalScrollController oldWidget) => | ||
49 | + controller != oldWidget.controller; | ||
50 | + | ||
51 | + @override | ||
52 | + void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||
53 | + super.debugFillProperties(properties); | ||
54 | + properties.add(DiagnosticsProperty<ScrollController>( | ||
55 | + 'controller', controller, | ||
56 | + ifNull: 'no controller', showName: false)); | ||
57 | + } | ||
58 | +} |
1 | import 'package:flutter/widgets.dart'; | 1 | import 'package:flutter/widgets.dart'; |
2 | 2 | ||
3 | -/// Creates a primary scroll controller that will | ||
4 | -/// scroll to the top when tapped on the status bar | 3 | +/// Widget that that will scroll to the top the ScrollController |
4 | +/// when tapped on the status bar | ||
5 | /// | 5 | /// |
6 | -class PrimaryScrollStatusBarHandler extends StatefulWidget { | 6 | +class ScrollToTopStatusBarHandler extends StatefulWidget { |
7 | final Widget child; | 7 | final Widget child; |
8 | + final ScrollController scrollController; | ||
8 | 9 | ||
9 | - const PrimaryScrollStatusBarHandler({Key key, this.child}) : super(key: key); | 10 | + const ScrollToTopStatusBarHandler({ |
11 | + Key key, | ||
12 | + @required this.child, | ||
13 | + @required this.scrollController, | ||
14 | + }) : super(key: key); | ||
10 | 15 | ||
11 | @override | 16 | @override |
12 | - _PrimaryScrollWidgetState createState() => _PrimaryScrollWidgetState(); | 17 | + _ScrollToTopStatusBarState createState() => _ScrollToTopStatusBarState(); |
13 | } | 18 | } |
14 | 19 | ||
15 | -class _PrimaryScrollWidgetState extends State<PrimaryScrollStatusBarHandler> { | 20 | +class _ScrollToTopStatusBarState extends State<ScrollToTopStatusBarHandler> { |
16 | @override | 21 | @override |
17 | void initState() { | 22 | void initState() { |
18 | super.initState(); | 23 | super.initState(); |
@@ -43,7 +48,7 @@ class _PrimaryScrollWidgetState extends State<PrimaryScrollStatusBarHandler> { | @@ -43,7 +48,7 @@ class _PrimaryScrollWidgetState extends State<PrimaryScrollStatusBarHandler> { | ||
43 | } | 48 | } |
44 | 49 | ||
45 | void _handleStatusBarTap(BuildContext context) { | 50 | void _handleStatusBarTap(BuildContext context) { |
46 | - final controller = PrimaryScrollController.of(context); | 51 | + final controller = widget.scrollController; |
47 | if (controller != null && controller.hasClients) { | 52 | if (controller != null && controller.hasClients) { |
48 | controller.animateTo( | 53 | controller.animateTo( |
49 | 0.0, | 54 | 0.0, |
-
Please register or login to post a comment