From 400c103712e00b069a98f5d54e1bbd6ea49433b4 Mon Sep 17 00:00:00 2001 From: Hrishikesh Date: Wed, 18 Dec 2024 13:01:22 +0530 Subject: [PATCH] null safety improvements --- lib/carousel_controller.dart | 58 +++++++++++++++++++----------------- lib/carousel_options.dart | 2 +- lib/carousel_slider.dart | 47 ++++++++++++++--------------- lib/carousel_state.dart | 11 +++++-- 4 files changed, 62 insertions(+), 56 deletions(-) diff --git a/lib/carousel_controller.dart b/lib/carousel_controller.dart index 280f996..b8a5f8d 100644 --- a/lib/carousel_controller.dart +++ b/lib/carousel_controller.dart @@ -11,13 +11,13 @@ abstract class CarouselSliderController { Future get onReady; - Future nextPage({Duration? duration, Curve? curve}); + Future nextPage({Duration duration, Curve curve}); - Future previousPage({Duration? duration, Curve? curve}); + Future previousPage({Duration duration, Curve curve}); void jumpToPage(int page); - Future animateToPage(int page, {Duration? duration, Curve? curve}); + Future animateToPage(int page, {Duration duration, Curve curve}); void startAutoPlay(); @@ -39,7 +39,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController { } void _setModeController() => - _state!.changeMode(CarouselPageChangedReason.controller); + _state?.changeMode(CarouselPageChangedReason.controller); @override bool get ready => _state != null; @@ -52,14 +52,16 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// The animation lasts for the given duration and follows the given curve. /// The returned [Future] resolves when the animation completes. Future nextPage( - {Duration? duration = const Duration(milliseconds: 300), - Curve? curve = Curves.linear}) async { + {Duration duration = const Duration(milliseconds: 300), + Curve curve = Curves.linear}) async { + if (_state == null) return; final bool isNeedResetTimer = _state!.options.pauseAutoPlayOnManualNavigate; if (isNeedResetTimer) { _state!.onResetTimer(); } _setModeController(); - await _state!.pageController!.nextPage(duration: duration!, curve: curve!); + await _state!.pageController.nextPage(duration: duration, curve: curve); + if (isNeedResetTimer) { _state!.onResumeTimer(); } @@ -70,15 +72,16 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// The animation lasts for the given duration and follows the given curve. /// The returned [Future] resolves when the animation completes. Future previousPage( - {Duration? duration = const Duration(milliseconds: 300), - Curve? curve = Curves.linear}) async { + {Duration duration = const Duration(milliseconds: 300), + Curve curve = Curves.linear}) async { + if (_state == null) return; final bool isNeedResetTimer = _state!.options.pauseAutoPlayOnManualNavigate; if (isNeedResetTimer) { _state!.onResetTimer(); } _setModeController(); - await _state!.pageController! - .previousPage(duration: duration!, curve: curve!); + await _state!.pageController.previousPage(duration: duration, curve: curve); + if (isNeedResetTimer) { _state!.onResumeTimer(); } @@ -89,12 +92,12 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// Jumps the page position from its current value to the given value, /// without animation, and without checking if the new value is in range. void jumpToPage(int page) { - final index = getRealIndex(_state!.pageController!.page!.toInt(), + if (_state == null) return; + getRealIndex(_state!.pageController.page!.toInt(), _state!.realPage - _state!.initialPage, _state!.itemCount); - _setModeController(); - final int pageToJump = _state!.pageController!.page!.toInt() + page - index; - return _state!.pageController!.jumpToPage(pageToJump); + final int pageToJump = _state!.pageController.page!.toInt(); + return _state!.pageController.jumpToPage(pageToJump); } /// Animates the controlled [CarouselSlider] from the current page to the given page. @@ -102,30 +105,31 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// The animation lasts for the given duration and follows the given curve. /// The returned [Future] resolves when the animation completes. Future animateToPage(int page, - {Duration? duration = const Duration(milliseconds: 300), - Curve? curve = Curves.linear}) async { + {Duration duration = const Duration(milliseconds: 300), + Curve curve = Curves.linear}) async { + if (_state == null) return; final bool isNeedResetTimer = _state!.options.pauseAutoPlayOnManualNavigate; if (isNeedResetTimer) { _state!.onResetTimer(); } - final index = getRealIndex(_state!.pageController!.page!.toInt(), + final index = getRealIndex(_state!.pageController.page!.toInt(), _state!.realPage - _state!.initialPage, _state!.itemCount); + int smallestMovement = page - index; if (_state!.options.enableInfiniteScroll && - _state!.itemCount != null && _state!.options.animateToClosest) { - if ((page - index).abs() > (page + _state!.itemCount! - index).abs()) { - smallestMovement = page + _state!.itemCount! - index; + if ((page - index).abs() > (page + (_state!.itemCount) - index).abs()) { + smallestMovement = page + (_state!.itemCount) - index; } else if ((page - index).abs() > - (page - _state!.itemCount! - index).abs()) { - smallestMovement = page - _state!.itemCount! - index; + (page - (_state!.itemCount) - index).abs()) { + smallestMovement = page - (_state!.itemCount) - index; } } _setModeController(); - await _state!.pageController!.animateToPage( - _state!.pageController!.page!.toInt() + smallestMovement, - duration: duration!, - curve: curve!); + await _state!.pageController.animateToPage( + (_state!.pageController.page!.toInt()) + smallestMovement, + duration: duration, + curve: curve); if (isNeedResetTimer) { _state!.onResumeTimer(); } diff --git a/lib/carousel_options.dart b/lib/carousel_options.dart index e19b85c..a1d3abe 100644 --- a/lib/carousel_options.dart +++ b/lib/carousel_options.dart @@ -64,7 +64,7 @@ class CarouselOptions { /// creating a feeling of depth in the carousel. /// /// Defaults to false. - final bool? enlargeCenterPage; + final bool enlargeCenterPage; /// The axis along which the page view scrolls. /// diff --git a/lib/carousel_slider.dart b/lib/carousel_slider.dart index e64ae29..bf5be4c 100644 --- a/lib/carousel_slider.dart +++ b/lib/carousel_slider.dart @@ -33,7 +33,7 @@ class CarouselSlider extends StatefulWidget { /// A [MapController], used to control the map. final CarouselSliderControllerImpl _carouselController; - final int? itemCount; + final int itemCount; CarouselSlider( {required this.items, @@ -96,7 +96,7 @@ class CarouselSliderState extends State viewportFraction: options.viewportFraction, initialPage: carouselState!.realPage, ); - carouselState!.pageController = pageController; + carouselState!.pageController = pageController!; // handle autoplay when state changes handleAutoPlay(); @@ -107,8 +107,8 @@ class CarouselSliderState extends State @override void initState() { super.initState(); - carouselState = - CarouselState(this.options, clearTimer, resumeTimer, this.changeMode); + carouselState = CarouselState(this.options, clearTimer, resumeTimer, + this.changeMode, widget.itemCount); carouselState!.itemCount = widget.itemCount; carouselController.state = carouselState; @@ -123,7 +123,7 @@ class CarouselSliderState extends State initialPage: carouselState!.realPage, ); - carouselState!.pageController = pageController; + carouselState!.pageController = pageController!; } Timer? getTimer() { @@ -141,10 +141,9 @@ class CarouselSliderState extends State CarouselPageChangedReason previousReason = mode; changeMode(CarouselPageChangedReason.timed); - int nextPage = carouselState!.pageController!.page!.round() + 1; - int itemCount = widget.itemCount ?? widget.items!.length; + int nextPage = carouselState!.pageController.page!.round() + 1; - if (nextPage >= itemCount && + if (nextPage >= widget.itemCount && widget.options.enableInfiniteScroll == false) { if (widget.options.pauseAutoPlayInFiniteScroll) { clearTimer(); @@ -153,7 +152,7 @@ class CarouselSliderState extends State nextPage = 0; } - carouselState!.pageController! + carouselState?.pageController .animateToPage(nextPage, duration: widget.options.autoPlayAnimationDuration, curve: widget.options.autoPlayCurve) @@ -200,7 +199,7 @@ class CarouselSliderState extends State onNotification: (Notification notification) { if (widget.options.onScrolled != null && notification is ScrollUpdateNotification) { - widget.options.onScrolled!(carouselState!.pageController!.page); + widget.options.onScrolled!(carouselState?.pageController.page); } return false; }, @@ -233,7 +232,7 @@ class CarouselSliderState extends State onNotification: (Notification notification) { if (widget.options.onScrolled != null && notification is ScrollUpdateNotification) { - widget.options.onScrolled!(carouselState!.pageController!.page); + widget.options.onScrolled!(carouselState!.pageController.page); } return false; }, @@ -330,30 +329,28 @@ class CarouselSliderState extends State carouselState!.realPage, widget.itemCount); return AnimatedBuilder( - animation: carouselState!.pageController!, - child: (widget.items != null) - ? (widget.items!.length > 0 ? widget.items![index] : Container()) - : widget.itemBuilder!(context, index, idx), + animation: carouselState!.pageController, + child: widget.itemBuilder?.call(context, index, idx) ?? + widget.items![index], builder: (BuildContext context, child) { double distortionValue = 1.0; // if `enlargeCenterPage` is true, we must calculate the carousel item's height // to display the visual effect double itemOffset = 0; - if (widget.options.enlargeCenterPage != null && - widget.options.enlargeCenterPage == true) { + if (widget.options.enlargeCenterPage == true) { // pageController.page can only be accessed after the first build, // so in the first build we calculate the itemoffset manually - var position = carouselState?.pageController?.position; - if (position != null && - position.hasPixels && - position.hasContentDimensions) { - var _page = carouselState?.pageController?.page; + var position = carouselState?.pageController.position; + if (position!.hasPixels && position.hasContentDimensions) { + var _page = carouselState?.pageController.page; + if (_page != null) { itemOffset = _page - idx; } } else { BuildContext storageContext = carouselState! - .pageController!.position.context.storageContext; + .pageController.position.context.storageContext; + final double? previousSavedPosition = PageStorage.of(storageContext).readState(storageContext) as double?; @@ -374,7 +371,7 @@ class CarouselSliderState extends State } final double height = widget.options.height ?? - MediaQuery.of(context).size.width * + MediaQuery.sizeOf(context).width * (1 / widget.options.aspectRatio); if (widget.options.scrollDirection == Axis.horizontal) { @@ -384,7 +381,7 @@ class CarouselSliderState extends State itemOffset: itemOffset)); } else { return getCenterWrapper(getEnlargeWrapper(child, - width: distortionValue * MediaQuery.of(context).size.width, + width: distortionValue * MediaQuery.sizeOf(context).width, scale: distortionValue, itemOffset: itemOffset)); } diff --git a/lib/carousel_state.dart b/lib/carousel_state.dart index b69e07d..395801b 100644 --- a/lib/carousel_state.dart +++ b/lib/carousel_state.dart @@ -7,7 +7,7 @@ class CarouselState { /// [pageController] is created using the properties passed to the constructor /// and can be used to control the [PageView] it is passed to. - PageController? pageController; + late PageController pageController; /// The actual index of the [PageView]. /// @@ -21,7 +21,7 @@ class CarouselState { int initialPage = 0; /// The widgets count that should be shown at carousel - int? itemCount; + int itemCount; /// Will be called when using pageController to go to next page or /// previous page. It will clear the autoPlay timer. @@ -37,5 +37,10 @@ class CarouselState { Function(CarouselPageChangedReason) changeMode; CarouselState( - this.options, this.onResetTimer, this.onResumeTimer, this.changeMode); + this.options, + this.onResetTimer, + this.onResumeTimer, + this.changeMode, + this.itemCount, + ); }