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