From 0e9aadd7bc845bef2680502a10f77af59eb7e46f Mon Sep 17 00:00:00 2001 From: Dongmin Yu Date: Sun, 1 Sep 2024 01:09:11 +0900 Subject: [PATCH 1/2] simple code refactoring for darts conventions --- lib/carousel_controller.dart | 6 ++++++ lib/carousel_slider.dart | 28 +++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/carousel_controller.dart b/lib/carousel_controller.dart index 280f996..884f00d 100644 --- a/lib/carousel_controller.dart +++ b/lib/carousel_controller.dart @@ -51,6 +51,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// /// The animation lasts for the given duration and follows the given curve. /// The returned [Future] resolves when the animation completes. + @override Future nextPage( {Duration? duration = const Duration(milliseconds: 300), Curve? curve = Curves.linear}) async { @@ -69,6 +70,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// /// The animation lasts for the given duration and follows the given curve. /// The returned [Future] resolves when the animation completes. + @override Future previousPage( {Duration? duration = const Duration(milliseconds: 300), Curve? curve = Curves.linear}) async { @@ -88,6 +90,7 @@ 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. + @override void jumpToPage(int page) { final index = getRealIndex(_state!.pageController!.page!.toInt(), _state!.realPage - _state!.initialPage, _state!.itemCount); @@ -101,6 +104,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// /// The animation lasts for the given duration and follows the given curve. /// The returned [Future] resolves when the animation completes. + @override Future animateToPage(int page, {Duration? duration = const Duration(milliseconds: 300), Curve? curve = Curves.linear}) async { @@ -135,6 +139,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// /// The carousel will only autoPlay if the [autoPlay] parameter /// in [CarouselOptions] is true. + @override void startAutoPlay() { _state!.onResumeTimer(); } @@ -143,6 +148,7 @@ class CarouselSliderControllerImpl implements CarouselSliderController { /// /// This is a more on-demand way of doing this. Use the [autoPlay] /// parameter in [CarouselOptions] to specify the autoPlay behaviour of the carousel. + @override void stopAutoPlay() { _state!.onResetTimer(); } diff --git a/lib/carousel_slider.dart b/lib/carousel_slider.dart index e64ae29..cb309cc 100644 --- a/lib/carousel_slider.dart +++ b/lib/carousel_slider.dart @@ -13,7 +13,7 @@ import 'utils.dart'; export 'carousel_controller.dart'; export 'carousel_options.dart'; -typedef Widget ExtendedIndexedWidgetBuilder( +typedef ExtendedIndexedWidgetBuilder = Widget Function( BuildContext context, int index, int realIndex); class CarouselSlider extends StatefulWidget { @@ -82,8 +82,8 @@ class CarouselSliderState extends State CarouselSliderState(this.carouselController); - void changeMode(CarouselPageChangedReason _mode) { - mode = _mode; + void changeMode(CarouselPageChangedReason mode) { + mode = mode; } @override @@ -108,7 +108,7 @@ class CarouselSliderState extends State void initState() { super.initState(); carouselState = - CarouselState(this.options, clearTimer, resumeTimer, this.changeMode); + CarouselState(options, clearTimer, resumeTimer, changeMode); carouselState!.itemCount = widget.itemCount; carouselController.state = carouselState; @@ -170,9 +170,7 @@ class CarouselSliderState extends State } void resumeTimer() { - if (timer == null) { - timer = getTimer(); - } + timer ??= getTimer(); } void handleAutoPlay() { @@ -189,7 +187,7 @@ class CarouselSliderState extends State Widget getGestureWrapper(Widget child) { Widget wrapper; if (widget.options.height != null) { - wrapper = Container(height: widget.options.height, child: child); + wrapper = SizedBox(height: widget.options.height, child: child); } else { wrapper = AspectRatio(aspectRatio: widget.options.aspectRatio, child: child); @@ -257,7 +255,7 @@ class CarouselSliderState extends State double? scale, required double itemOffset}) { if (widget.options.enlargeStrategy == CenterPageEnlargeStrategy.height) { - return SizedBox(child: child, width: width, height: height); + return SizedBox(width: width, height: height, child: child); } if (widget.options.enlargeStrategy == CenterPageEnlargeStrategy.zoom) { late Alignment alignment; @@ -267,11 +265,11 @@ class CarouselSliderState extends State } else { alignment = horizontal ? Alignment.centerLeft : Alignment.topCenter; } - return Transform.scale(child: child, scale: scale!, alignment: alignment); + return Transform.scale(scale: scale!, alignment: alignment, child: child); } return Transform.scale( scale: scale!, - child: Container(child: child, width: width, height: height)); + child: SizedBox(width: width, height: height, child: child)); } void onStart() { @@ -332,7 +330,7 @@ class CarouselSliderState extends State return AnimatedBuilder( animation: carouselState!.pageController!, child: (widget.items != null) - ? (widget.items!.length > 0 ? widget.items![index] : Container()) + ? (widget.items!.isNotEmpty ? widget.items![index] : Container()) : widget.itemBuilder!(context, index, idx), builder: (BuildContext context, child) { double distortionValue = 1.0; @@ -347,9 +345,9 @@ class CarouselSliderState extends State if (position != null && position.hasPixels && position.hasContentDimensions) { - var _page = carouselState?.pageController?.page; - if (_page != null) { - itemOffset = _page - idx; + var page = carouselState?.pageController?.page; + if (page != null) { + itemOffset = page - idx; } } else { BuildContext storageContext = carouselState! From ef06fee9104bbbeb086dbe797f1656772075fae6 Mon Sep 17 00:00:00 2001 From: Dongmin Yu Date: Sun, 1 Sep 2024 01:12:02 +0900 Subject: [PATCH 2/2] add widget keys and the `const` keyword in the example app --- example/lib/main.dart | 184 +++++++++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 74 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 3e860d6..95989a9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -10,11 +10,13 @@ final List imgList = [ 'https://images.unsplash.com/photo-1519985176271-adb1088fa94c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a0c8d632e977f94e5d312d9893258f59&auto=format&fit=crop&w=1355&q=80' ]; -void main() => runApp(CarouselDemo()); +void main() => runApp(const CarouselDemo()); final themeMode = ValueNotifier(2); class CarouselDemo extends StatelessWidget { + const CarouselDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ValueListenableBuilder( @@ -25,23 +27,23 @@ class CarouselDemo extends StatelessWidget { themeMode: ThemeMode.values.toList()[value as int], debugShowCheckedModeBanner: false, routes: { - '/': (ctx) => CarouselDemoHome(), - '/basic': (ctx) => BasicDemo(), - '/nocenter': (ctx) => NoCenterDemo(), - '/image': (ctx) => ImageSliderDemo(), - '/complicated': (ctx) => ComplicatedImageDemo(), - '/enlarge': (ctx) => EnlargeStrategyDemo(), - '/manual': (ctx) => ManuallyControlledSlider(), - '/noloop': (ctx) => NoonLoopingDemo(), - '/vertical': (ctx) => VerticalSliderDemo(), - '/fullscreen': (ctx) => FullscreenSliderDemo(), - '/ondemand': (ctx) => OnDemandCarouselDemo(), - '/indicator': (ctx) => CarouselWithIndicatorDemo(), - '/prefetch': (ctx) => PrefetchImageDemo(), - '/reason': (ctx) => CarouselChangeReasonDemo(), - '/position': (ctx) => KeepPageviewPositionDemo(), - '/multiple': (ctx) => MultipleItemDemo(), - '/zoom': (ctx) => EnlargeStrategyZoomDemo(), + '/': (ctx) => const CarouselDemoHome(), + '/basic': (ctx) => const BasicDemo(), + '/nocenter': (ctx) => const NoCenterDemo(), + '/image': (ctx) => const ImageSliderDemo(), + '/complicated': (ctx) => const ComplicatedImageDemo(), + '/enlarge': (ctx) => const EnlargeStrategyDemo(), + '/manual': (ctx) => const ManuallyControlledSlider(), + '/noloop': (ctx) => const NoonLoopingDemo(), + '/vertical': (ctx) => const VerticalSliderDemo(), + '/fullscreen': (ctx) => const FullscreenSliderDemo(), + '/ondemand': (ctx) => const OnDemandCarouselDemo(), + '/indicator': (ctx) => const CarouselWithIndicatorDemo(), + '/prefetch': (ctx) => const PrefetchImageDemo(), + '/reason': (ctx) => const CarouselChangeReasonDemo(), + '/position': (ctx) => const KeepPageviewPositionDemo(), + '/multiple': (ctx) => const MultipleItemDemo(), + '/zoom': (ctx) => const EnlargeStrategyZoomDemo(), }, ); }, @@ -53,7 +55,7 @@ class CarouselDemo extends StatelessWidget { class DemoItem extends StatelessWidget { final String title; final String route; - DemoItem(this.title, this.route); + const DemoItem(this.title, this.route, {Key? key}) : super(key: key); @override Widget build(BuildContext context) { @@ -67,21 +69,23 @@ class DemoItem extends StatelessWidget { } class CarouselDemoHome extends StatelessWidget { + const CarouselDemoHome({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('Carousel demo'), + title: const Text('Carousel demo'), actions: [ IconButton( - icon: Icon(Icons.nightlight_round), + icon: const Icon(Icons.nightlight_round), onPressed: () { themeMode.value = themeMode.value == 1 ? 2 : 1; }) ], ), body: ListView( - children: [ + children: const [ DemoItem('Basic demo', '/basic'), DemoItem('No center mode demo', '/nocenter'), DemoItem('Image carousel slider', '/image'), @@ -105,18 +109,20 @@ class CarouselDemoHome extends StatelessWidget { } class BasicDemo extends StatelessWidget { + const BasicDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { List list = [1, 2, 3, 4, 5]; return Scaffold( - appBar: AppBar(title: Text('Basic demo')), - body: Container( + appBar: AppBar(title: const Text('Basic demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions(), items: list .map((item) => Container( - child: Center(child: Text(item.toString())), color: Colors.green, + child: Center(child: Text(item.toString())), )) .toList(), )), @@ -125,20 +131,22 @@ class BasicDemo extends StatelessWidget { } class NoCenterDemo extends StatelessWidget { + const NoCenterDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { List list = [1, 2, 3, 4, 5]; return Scaffold( - appBar: AppBar(title: Text('Basic demo')), - body: Container( + appBar: AppBar(title: const Text('Basic demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions( disableCenter: true, ), items: list .map((item) => Container( - child: Text(item.toString()), color: Colors.green, + child: Text(item.toString()), )) .toList(), )), @@ -147,15 +155,17 @@ class NoCenterDemo extends StatelessWidget { } class ImageSliderDemo extends StatelessWidget { + const ImageSliderDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Image slider demo')), - body: Container( + appBar: AppBar(title: const Text('Image slider demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions(), items: imgList - .map((item) => Container( + .map((item) => SizedBox( child: Center( child: Image.network(item, fit: BoxFit.cover, width: 1000)), @@ -167,11 +177,11 @@ class ImageSliderDemo extends StatelessWidget { } final List imageSliders = imgList - .map((item) => Container( + .map((item) => SizedBox( child: Container( - margin: EdgeInsets.all(5.0), + margin: const EdgeInsets.all(5.0), child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5.0)), + borderRadius: const BorderRadius.all(Radius.circular(5.0)), child: Stack( children: [ Image.network(item, fit: BoxFit.cover, width: 1000.0), @@ -180,7 +190,7 @@ final List imageSliders = imgList left: 0.0, right: 0.0, child: Container( - decoration: BoxDecoration( + decoration: const BoxDecoration( gradient: LinearGradient( colors: [ Color.fromARGB(200, 0, 0, 0), @@ -190,11 +200,11 @@ final List imageSliders = imgList end: Alignment.topCenter, ), ), - padding: EdgeInsets.symmetric( + padding: const EdgeInsets.symmetric( vertical: 10.0, horizontal: 20.0), child: Text( 'No. ${imgList.indexOf(item)} image', - style: TextStyle( + style: const TextStyle( color: Colors.white, fontSize: 20.0, fontWeight: FontWeight.bold, @@ -209,11 +219,13 @@ final List imageSliders = imgList .toList(); class ComplicatedImageDemo extends StatelessWidget { + const ComplicatedImageDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Complicated image slider demo')), - body: Container( + appBar: AppBar(title: const Text('Complicated image slider demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions( autoPlay: true, @@ -228,11 +240,13 @@ class ComplicatedImageDemo extends StatelessWidget { } class EnlargeStrategyDemo extends StatelessWidget { + const EnlargeStrategyDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Complicated image slider demo')), - body: Container( + appBar: AppBar(title: const Text('Complicated image slider demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions( autoPlay: true, @@ -248,6 +262,8 @@ class EnlargeStrategyDemo extends StatelessWidget { } class ManuallyControlledSlider extends StatefulWidget { + const ManuallyControlledSlider({Key? key}) : super(key: key); + @override State createState() { return _ManuallyControlledSliderState(); @@ -265,7 +281,7 @@ class _ManuallyControlledSliderState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Manually controlled slider')), + appBar: AppBar(title: const Text('Manually controlled slider')), body: SingleChildScrollView( child: Column( children: [ @@ -280,13 +296,13 @@ class _ManuallyControlledSliderState extends State { Flexible( child: ElevatedButton( onPressed: () => _controller.previousPage(), - child: Text('←'), + child: const Text('←'), ), ), Flexible( child: ElevatedButton( onPressed: () => _controller.nextPage(), - child: Text('→'), + child: const Text('→'), ), ), ...Iterable.generate(imgList.length).map( @@ -306,11 +322,13 @@ class _ManuallyControlledSliderState extends State { } class NoonLoopingDemo extends StatelessWidget { + const NoonLoopingDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Noon-looping carousel demo')), - body: Container( + appBar: AppBar(title: const Text('Noon-looping carousel demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions( aspectRatio: 2.0, @@ -326,11 +344,13 @@ class NoonLoopingDemo extends StatelessWidget { } class VerticalSliderDemo extends StatelessWidget { + const VerticalSliderDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Vertical sliding carousel demo')), - body: Container( + appBar: AppBar(title: const Text('Vertical sliding carousel demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions( aspectRatio: 2.0, @@ -345,10 +365,12 @@ class VerticalSliderDemo extends StatelessWidget { } class FullscreenSliderDemo extends StatelessWidget { + const FullscreenSliderDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Fullscreen sliding carousel demo')), + appBar: AppBar(title: const Text('Fullscreen sliding carousel demo')), body: Builder( builder: (context) { final double height = MediaQuery.of(context).size.height; @@ -360,7 +382,7 @@ class FullscreenSliderDemo extends StatelessWidget { // autoPlay: false, ), items: imgList - .map((item) => Container( + .map((item) => SizedBox( child: Center( child: Image.network( item, @@ -377,11 +399,13 @@ class FullscreenSliderDemo extends StatelessWidget { } class OnDemandCarouselDemo extends StatelessWidget { + const OnDemandCarouselDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('On-demand carousel demo')), - body: Container( + appBar: AppBar(title: const Text('On-demand carousel demo')), + body: SizedBox( child: CarouselSlider.builder( itemCount: 100, options: CarouselOptions( @@ -390,7 +414,7 @@ class OnDemandCarouselDemo extends StatelessWidget { autoPlay: true, ), itemBuilder: (ctx, index, realIdx) { - return Container( + return SizedBox( child: Text(index.toString()), ); }, @@ -400,6 +424,8 @@ class OnDemandCarouselDemo extends StatelessWidget { } class CarouselWithIndicatorDemo extends StatefulWidget { + const CarouselWithIndicatorDemo({Key? key}) : super(key: key); + @override State createState() { return _CarouselWithIndicatorState(); @@ -413,7 +439,7 @@ class _CarouselWithIndicatorState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Carousel with indicator controller demo')), + appBar: AppBar(title: const Text('Carousel with indicator controller demo')), body: Column(children: [ Expanded( child: CarouselSlider( @@ -438,7 +464,7 @@ class _CarouselWithIndicatorState extends State { child: Container( width: 12.0, height: 12.0, - margin: EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0), + margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0), decoration: BoxDecoration( shape: BoxShape.circle, color: (Theme.of(context).brightness == Brightness.dark @@ -455,6 +481,8 @@ class _CarouselWithIndicatorState extends State { } class PrefetchImageDemo extends StatefulWidget { + const PrefetchImageDemo({Key? key}) : super(key: key); + @override State createState() { return _PrefetchImageDemoState(); @@ -475,9 +503,9 @@ class _PrefetchImageDemoState extends State { @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) { - images.forEach((imageUrl) { + for (var imageUrl in images) { precacheImage(NetworkImage(imageUrl), context); - }); + } }); super.initState(); } @@ -485,8 +513,8 @@ class _PrefetchImageDemoState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Prefetch image slider demo')), - body: Container( + appBar: AppBar(title: const Text('Prefetch image slider demo')), + body: SizedBox( child: CarouselSlider.builder( itemCount: images.length, options: CarouselOptions( @@ -495,7 +523,7 @@ class _PrefetchImageDemoState extends State { enlargeCenterPage: true, ), itemBuilder: (context, index, realIdx) { - return Container( + return SizedBox( child: Center( child: Image.network(images[index], fit: BoxFit.cover, width: 1000)), @@ -507,6 +535,8 @@ class _PrefetchImageDemoState extends State { } class CarouselChangeReasonDemo extends StatefulWidget { + const CarouselChangeReasonDemo({Key? key}) : super(key: key); + @override State createState() { return _CarouselChangeReasonDemoState(); @@ -526,7 +556,7 @@ class _CarouselChangeReasonDemoState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Change reason demo')), + appBar: AppBar(title: const Text('Change reason demo')), body: Column( children: [ Expanded( @@ -547,13 +577,13 @@ class _CarouselChangeReasonDemoState extends State { Flexible( child: ElevatedButton( onPressed: () => _controller.previousPage(), - child: Text('←'), + child: const Text('←'), ), ), Flexible( child: ElevatedButton( onPressed: () => _controller.nextPage(), - child: Text('→'), + child: const Text('→'), ), ), ...Iterable.generate(imgList.length).map( @@ -569,7 +599,7 @@ class _CarouselChangeReasonDemoState extends State { Center( child: Column( children: [ - Text('page change reason: '), + const Text('page change reason: '), Text(reason), ], ), @@ -580,27 +610,29 @@ class _CarouselChangeReasonDemoState extends State { } class KeepPageviewPositionDemo extends StatelessWidget { + const KeepPageviewPositionDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Keep pageview position demo')), + appBar: AppBar(title: const Text('Keep pageview position demo')), body: ListView.builder(itemBuilder: (ctx, index) { if (index == 3) { - return Container( + return SizedBox( child: CarouselSlider( options: CarouselOptions( aspectRatio: 2.0, enlargeCenterPage: true, - pageViewKey: PageStorageKey('carousel_slider'), + pageViewKey: const PageStorageKey('carousel_slider'), ), items: imageSliders, )); } else { return Container( - margin: EdgeInsets.symmetric(vertical: 20), + margin: const EdgeInsets.symmetric(vertical: 20), color: Colors.blue, height: 200, - child: Center( + child: const Center( child: Text('other content'), ), ); @@ -611,11 +643,13 @@ class KeepPageviewPositionDemo extends StatelessWidget { } class MultipleItemDemo extends StatelessWidget { + const MultipleItemDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('Multiple item in one slide demo')), - body: Container( + appBar: AppBar(title: const Text('Multiple item in one slide demo')), + body: SizedBox( child: CarouselSlider.builder( options: CarouselOptions( aspectRatio: 2.0, @@ -631,7 +665,7 @@ class MultipleItemDemo extends StatelessWidget { return Expanded( flex: 1, child: Container( - margin: EdgeInsets.symmetric(horizontal: 10), + margin: const EdgeInsets.symmetric(horizontal: 10), child: Image.network(imgList[idx], fit: BoxFit.cover), ), ); @@ -644,11 +678,13 @@ class MultipleItemDemo extends StatelessWidget { } class EnlargeStrategyZoomDemo extends StatelessWidget { + const EnlargeStrategyZoomDemo({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text('enlarge strategy: zoom demo')), - body: Container( + appBar: AppBar(title: const Text('enlarge strategy: zoom demo')), + body: SizedBox( child: CarouselSlider( options: CarouselOptions( aspectRatio: 2.0,