Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

null safety improvements #480

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 31 additions & 27 deletions lib/carousel_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ abstract class CarouselSliderController {

Future<Null> get onReady;

Future<void> nextPage({Duration? duration, Curve? curve});
Future<void> nextPage({Duration duration, Curve curve});

Future<void> previousPage({Duration? duration, Curve? curve});
Future<void> previousPage({Duration duration, Curve curve});

void jumpToPage(int page);

Future<void> animateToPage(int page, {Duration? duration, Curve? curve});
Future<void> animateToPage(int page, {Duration duration, Curve curve});

void startAutoPlay();

Expand All @@ -39,7 +39,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController {
}

void _setModeController() =>
_state!.changeMode(CarouselPageChangedReason.controller);
_state?.changeMode(CarouselPageChangedReason.controller);

@override
bool get ready => _state != null;
Expand All @@ -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<void> 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();
}
Expand All @@ -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<void> 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();
}
Expand All @@ -89,43 +92,44 @@ 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.
///
/// The animation lasts for the given duration and follows the given curve.
/// The returned [Future] resolves when the animation completes.
Future<void> 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();
}
Expand Down
2 changes: 1 addition & 1 deletion lib/carousel_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
47 changes: 22 additions & 25 deletions lib/carousel_slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -96,7 +96,7 @@ class CarouselSliderState extends State<CarouselSlider>
viewportFraction: options.viewportFraction,
initialPage: carouselState!.realPage,
);
carouselState!.pageController = pageController;
carouselState!.pageController = pageController!;

// handle autoplay when state changes
handleAutoPlay();
Expand All @@ -107,8 +107,8 @@ class CarouselSliderState extends State<CarouselSlider>
@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;
Expand All @@ -123,7 +123,7 @@ class CarouselSliderState extends State<CarouselSlider>
initialPage: carouselState!.realPage,
);

carouselState!.pageController = pageController;
carouselState!.pageController = pageController!;
}

Timer? getTimer() {
Expand All @@ -141,10 +141,9 @@ class CarouselSliderState extends State<CarouselSlider>

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();
Expand All @@ -153,7 +152,7 @@ class CarouselSliderState extends State<CarouselSlider>
nextPage = 0;
}

carouselState!.pageController!
carouselState?.pageController
.animateToPage(nextPage,
duration: widget.options.autoPlayAnimationDuration,
curve: widget.options.autoPlayCurve)
Expand Down Expand Up @@ -200,7 +199,7 @@ class CarouselSliderState extends State<CarouselSlider>
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;
},
Expand Down Expand Up @@ -233,7 +232,7 @@ class CarouselSliderState extends State<CarouselSlider>
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;
},
Expand Down Expand Up @@ -330,30 +329,28 @@ class CarouselSliderState extends State<CarouselSlider>
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?;
Expand All @@ -374,7 +371,7 @@ class CarouselSliderState extends State<CarouselSlider>
}

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) {
Expand All @@ -384,7 +381,7 @@ class CarouselSliderState extends State<CarouselSlider>
itemOffset: itemOffset));
} else {
return getCenterWrapper(getEnlargeWrapper(child,
width: distortionValue * MediaQuery.of(context).size.width,
width: distortionValue * MediaQuery.sizeOf(context).width,
scale: distortionValue,
itemOffset: itemOffset));
}
Expand Down
11 changes: 8 additions & 3 deletions lib/carousel_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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].
///
Expand All @@ -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.
Expand All @@ -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,
);
}