diff --git a/example/assets/code_snippets/carousel.md b/example/assets/code_snippets/carousel.md index be65888c..3e28bc27 100644 --- a/example/assets/code_snippets/carousel.md +++ b/example/assets/code_snippets/carousel.md @@ -1,30 +1,77 @@ import 'package:flutter/material.dart'; import 'package:moon_design/moon_design.dart'; -class Carousel extends StatelessWidget { +class Carousel extends StatefulWidget { const Carousel({super.key}); + @override + State createState() => _CarouselState(); +} + +class _CarouselState extends State { + int selectedDot = 0; + @override Widget build(BuildContext context) { - return OverflowBox( - maxWidth: MediaQuery.of(context).size.width, - minHeight: 110, - maxHeight: 110, - child: MoonCarousel( - itemCount: 10, - itemExtent: 110, - itemBuilder: (BuildContext context, int itemIndex, int _) => Container( - decoration: ShapeDecoration( - color: context.moonColors!.goku, - shape: MoonSquircleBorder( - borderRadius: BorderRadius.circular(12).squircleBorderRadius(context), + return Column( + children: [ + // Default MoonCarousel. + SizedBox( + height: 110, + child: OverflowBox( + maxWidth: MediaQuery.of(context).size.width, + child: MoonCarousel( + itemCount: 10, + itemExtent: 110, + itemBuilder: (BuildContext context, int itemIndex, int _) => Container( + decoration: ShapeDecoration( + color: context.moonColors!.goku, + shape: MoonSquircleBorder( + borderRadius: BorderRadius.circular(12).squircleBorderRadius(context), + ), + ), + child: Center( + child: Text("${itemIndex + 1}"), + ), + ), ), ), - child: Center( - child: Text("${itemIndex + 1}"), - ), ), - ), + + // Full width MoonCarousel with MoonDotIndicator. + Column( + children: [ + SizedBox( + height: 180, + child: OverflowBox( + maxWidth: MediaQuery.of(context).size.width, + child: MoonCarousel( + gap: 32, + itemCount: 5, + itemExtent: MediaQuery.of(context).size.width - 32, + physics: const PageScrollPhysics(), + onIndexChanged: (int index) => setState(() => selectedDot = index), + itemBuilder: (BuildContext context, int itemIndex, int _) => Container( + decoration: ShapeDecoration( + color: context.moonColors!.goku, + shape: MoonSquircleBorder( + borderRadius: BorderRadius.circular(12).squircleBorderRadius(context), + ), + ), + child: Center( + child: Text("${itemIndex + 1}"), + ), + ), + ), + ), + ), + MoonDotIndicator( + selectedDot: selectedDot, + dotCount: 5, + ), + ], + ), + ], ); } -} \ No newline at end of file +} diff --git a/example/lib/src/storybook/stories/carousel.dart b/example/lib/src/storybook/stories/carousel.dart index b34909bc..b90ce50a 100644 --- a/example/lib/src/storybook/stories/carousel.dart +++ b/example/lib/src/storybook/stories/carousel.dart @@ -100,14 +100,14 @@ class _CarouselStoryState extends State { child: OverflowBox( maxWidth: constraints.maxWidth, child: MoonCarousel( - velocityFactor: velocityFactorKnob ?? 0.5, gap: gapKnob?.toDouble() ?? 8, + velocityFactor: velocityFactorKnob ?? 0.5, + loop: isLoopedKnob, autoPlay: autoPlayKnob, + isCentered: isCenteredKnob, itemCount: 10, itemExtent: itemExtentKnob?.toDouble() ?? 114, - isCentered: isCenteredKnob, anchor: anchorKnob ?? 16 / (constraints.maxWidth - 16), - loop: isLoopedKnob, clampMaxExtent: clampMaxExtentKnob, itemBuilder: (BuildContext context, int itemIndex, int _) => Container( decoration: ShapeDecoration( @@ -133,12 +133,13 @@ class _CarouselStoryState extends State { child: Stack( children: [ MoonCarousel( - gap: 48, - controller: carouselController, - autoPlay: autoPlayKnob, + gap: 64, itemCount: 5, itemExtent: constraints.maxWidth - 64, loop: isLoopedKnob, + autoPlay: autoPlayKnob, + controller: carouselController, + physics: const PageScrollPhysics(), onIndexChanged: (int index) => setState(() => selectedDot = index), itemBuilder: (BuildContext context, int itemIndex, int _) => Container( decoration: ShapeDecoration( diff --git a/lib/src/widgets/carousel/carousel.dart b/lib/src/widgets/carousel/carousel.dart index 4efc990c..087326d0 100644 --- a/lib/src/widgets/carousel/carousel.dart +++ b/lib/src/widgets/carousel/carousel.dart @@ -119,12 +119,13 @@ class MoonCarousel extends StatefulWidget { } class _MoonCarouselState extends State { - late double _effectiveGap; late int _lastReportedItemIndex; late MoonCarouselScrollController _scrollController; final Key _forwardListKey = const ValueKey("moon_carousel_key"); + double _effectiveGap = 0; + // Calculates the anchor position for the viewport to center the selected item when 'isCentered' is true. double _getCenteredAnchor(BoxConstraints constraints) { if (!widget.isCentered) return widget.anchor; @@ -168,8 +169,6 @@ class _MoonCarouselState extends State { _lastReportedItemIndex = _scrollController.initialItem; - _effectiveGap = widget.gap ?? context.moonTheme?.carouselTheme.properties.gap ?? MoonSizes.sizes.x2s; - if (widget.autoPlay) { WidgetsBinding.instance.addPostFrameCallback((Duration _) { final Duration effectiveAutoPlayDelay = widget.autoPlayDelay ?? @@ -220,9 +219,6 @@ class _MoonCarouselState extends State { _scrollController.stopAutoplay(); } } - if (widget.gap != oldWidget.gap) { - _effectiveGap = widget.gap ?? context.moonTheme?.carouselTheme.properties.gap ?? MoonSizes.sizes.x2s; - } } @override @@ -293,6 +289,8 @@ class _MoonCarouselState extends State { }, ); + _effectiveGap = widget.gap ?? context.moonTheme?.carouselTheme.properties.gap ?? MoonSizes.sizes.x2s; + return NotificationListener( onNotification: (ScrollUpdateNotification notification) { final MoonCarouselExtentMetrics metrics = notification.metrics as MoonCarouselExtentMetrics;