diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2c57f6b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "example", + "cwd": "example", + "request": "launch", + "type": "dart", + "program": "lib/main.dart" + }, + { + "name": "example (profile mode)", + "cwd": "example", + "request": "launch", + "type": "dart", + "flutterMode": "profile", + "program": "lib/main.dart" + } + ] +} \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml index d4fcc1a..c61494c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +1,10 @@ -include: package:pedantic/analysis_options.yaml \ No newline at end of file +include: package:flutter_lints_plus/flutter.yaml + +linter: + rules: + prefer_relative_imports: false + sort_pub_dependencies: false + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/example/lib/InnerSwiper.dart b/example/lib/inner_swiper.dart similarity index 78% rename from example/lib/InnerSwiper.dart rename to example/lib/inner_swiper.dart index d6d839b..52760d7 100644 --- a/example/lib/InnerSwiper.dart +++ b/example/lib/inner_swiper.dart @@ -1,18 +1,22 @@ -import 'package:flutter/material.dart'; import 'package:card_swiper/card_swiper.dart'; +import 'package:flutter/material.dart'; -void main() => runApp(MyApp()); +void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { - return MaterialApp( + return const MaterialApp( home: InnerSwiper(), ); } } class InnerSwiper extends StatefulWidget { + const InnerSwiper({Key? key}) : super(key: key); + @override State createState() { return _InnerSwiperState(); @@ -41,19 +45,19 @@ class _InnerSwiperState extends State { loop: false, itemCount: 10, controller: controller, - pagination: SwiperPagination(), - itemBuilder: (BuildContext context, int index) { + pagination: const SwiperPagination(), + itemBuilder: (context, index) { return Column( children: [ SizedBox( child: Swiper( controller: controllers[index], - pagination: SwiperPagination(), + pagination: const SwiperPagination(), itemCount: 4, - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Container( color: Colors.greenAccent, - child: Text('jkfjkldsfjd'), + child: const Text('jkfjkldsfjd'), ); }, autoplay: autoPlayer[index], @@ -66,7 +70,7 @@ class _InnerSwiperState extends State { autoPlayer[index] = true; }); }, - child: Text('Start autoplay'), + child: const Text('Start autoplay'), ), ElevatedButton( onPressed: () { @@ -74,7 +78,7 @@ class _InnerSwiperState extends State { autoPlayer[index] = false; }); }, - child: Text('End autoplay'), + child: const Text('End autoplay'), ), Text('is autoplay: ${autoPlayer[index]}') ], diff --git a/example/lib/listener_test.dart b/example/lib/listener_test.dart index 6d7ae2b..11f05a8 100644 --- a/example/lib/listener_test.dart +++ b/example/lib/listener_test.dart @@ -1,42 +1,43 @@ -import 'package:flutter/material.dart'; import 'package:card_swiper/card_swiper.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; -void main() => runApp(new MyApp()); +void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + // This widget is the root of your application. @override Widget build(BuildContext context) { - return new MaterialApp( + return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), - home: new MyHomePage(title: 'Flutter Swiper'), + home: const MyHomePage(title: 'Flutter Swiper'), ); } } class MyHomePage extends StatefulWidget { - MyHomePage({Key? key, required this.title}) : super(key: key); + const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override - _MyHomePageState createState() => new _MyHomePageState(); + _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { @override Widget build(BuildContext context) { - return new Scaffold( - body: new Swiper( + return Scaffold( + body: Swiper( itemCount: 10, itemBuilder: (c, i) { - return new Text("$i"); + return Text('$i'); }, - plugins: [], + plugins: const [], ), ); } diff --git a/example/lib/main.dart b/example/lib/main.dart index a1539af..0fd06b5 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,32 +1,46 @@ -import 'package:example/src/ExampleCustom.dart'; -import 'package:example/src/ExampleSwiperInScrollView.dart'; -import 'package:example/src/config.dart'; -import 'package:flutter/material.dart'; +import 'dart:ui'; + import 'package:card_swiper/card_swiper.dart'; +import 'package:flutter/material.dart'; + +import 'src/config.dart'; +import 'src/example_custom.dart'; +import 'src/example_swiper_in_scrollview.dart'; -void main() => runApp(MyApp()); +void main() => runApp(const MyApp()); + +class MyScrollBehavior extends MaterialScrollBehavior { + @override + Set get dragDevices => { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + }; +} class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( + scrollBehavior: MyScrollBehavior(), title: 'Flutter Demo', theme: ThemeData.light(), - home: MyHomePage(title: 'Flutter Swiper'), + home: const MyHomePage(title: 'Flutter Swiper'), routes: { - '/example01': (BuildContext context) => ExampleHorizontal(), - '/example02': (BuildContext context) => ExampleVertical(), - '/example03': (BuildContext context) => ExampleFraction(), - '/example04': (BuildContext context) => ExampleCustomPagination(), - '/example05': (BuildContext context) => ExamplePhone(), - '/example06': (BuildContext context) => ScaffoldWidget( + '/example01': (context) => const ExampleHorizontal(), + '/example02': (context) => const ExampleVertical(), + '/example03': (context) => const ExampleFraction(), + '/example04': (context) => const ExampleCustomPagination(), + '/example05': (context) => const ExamplePhone(), + '/example06': (context) => const ScaffoldWidget( child: ExampleSwiperInScrollView(), - title: "ScrollView", + title: 'ScrollView', ), - '/example07': (BuildContext context) => ScaffoldWidget( + '/example07': (context) => const ScaffoldWidget( child: ExampleCustom(), - title: "Custom All", + title: 'Custom All', ) }, ); @@ -34,7 +48,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - MyHomePage({Key? key, required this.title}) : super(key: key); + const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @@ -43,12 +57,13 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - List render(BuildContext context, List children) { + List render(BuildContext context, List> children) { return ListTile.divideTiles( - context: context, - tiles: children.map((dynamic data) { - return buildListTile(context, data[0], data[1], data[2]); - })).toList(); + context: context, + tiles: children.map((data) { + return buildListTile(context, data[0], data[1], data[2]); + }), + ).toList(); } Widget buildListTile( @@ -62,7 +77,7 @@ class _MyHomePageState extends State { leading: null, title: Text(title), subtitle: Text(subtitle), - trailing: Icon( + trailing: const Icon( Icons.arrow_right, color: Colors.blueAccent, ), @@ -79,13 +94,13 @@ class _MyHomePageState extends State { ), body: ListView( children: render(context, [ - ["Horizontal", "Scroll Horizontal", "/example01"], - ["Vertical", "Scroll Vertical", "/example02"], - ["Fraction", "Fraction style", "/example03"], - ["Custom Pagination", "Custom Pagination", "/example04"], - ["Phone", "Phone view", "/example05"], - ["ScrollView ", "In a ScrollView", "/example06"], - ["Custom", "Custom all properties", "/example07"] + ['Horizontal', 'Scroll Horizontal', '/example01'], + ['Vertical', 'Scroll Vertical', '/example02'], + ['Fraction', 'Fraction style', '/example03'], + ['Custom Pagination', 'Custom Pagination', '/example04'], + ['Phone', 'Phone view', '/example05'], + ['ScrollView ', 'In a ScrollView', '/example06'], + ['Custom', 'Custom all properties', '/example07'] ]), ), ); @@ -93,44 +108,49 @@ class _MyHomePageState extends State { } const List titles = [ - "Flutter Swiper is awesome", - "Really nice", - "Yeah" + 'Flutter Swiper is awesome', + 'Really nice', + 'Yeah' ]; class ExampleHorizontal extends StatelessWidget { + const ExampleHorizontal({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("ExampleHorizontal"), + title: const Text('ExampleHorizontal'), ), body: Swiper( - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { + final image = images[index]; return Image.asset( - images[index], + image, fit: BoxFit.fill, ); }, indicatorLayout: PageIndicatorLayout.COLOR, autoplay: true, itemCount: images.length, - pagination: SwiperPagination(), - control: SwiperControl(), + pagination: const SwiperPagination(), + control: const SwiperControl(), ), ); } } class ExampleVertical extends StatelessWidget { + const ExampleVertical({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("ExampleVertical"), + title: const Text('ExampleVertical'), ), body: Swiper( - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Image.asset( images[index], fit: BoxFit.fill, @@ -139,24 +159,26 @@ class ExampleVertical extends StatelessWidget { autoplay: true, itemCount: images.length, scrollDirection: Axis.vertical, - pagination: SwiperPagination(alignment: Alignment.centerRight), - control: SwiperControl(), + pagination: const SwiperPagination(alignment: Alignment.centerRight), + control: const SwiperControl(), )); } } class ExampleFraction extends StatelessWidget { + const ExampleFraction({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("ExampleFraction"), + title: const Text('ExampleFraction'), ), body: Column( children: [ Expanded( child: Swiper( - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Image.asset( images[index], fit: BoxFit.fill, @@ -164,12 +186,13 @@ class ExampleFraction extends StatelessWidget { }, autoplay: true, itemCount: images.length, - pagination: SwiperPagination(builder: SwiperPagination.fraction), - control: SwiperControl(), + pagination: + const SwiperPagination(builder: SwiperPagination.fraction), + control: const SwiperControl(), )), Expanded( child: Swiper( - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Image.asset( images[index], fit: BoxFit.fill, @@ -178,7 +201,7 @@ class ExampleFraction extends StatelessWidget { autoplay: true, itemCount: images.length, scrollDirection: Axis.vertical, - pagination: SwiperPagination( + pagination: const SwiperPagination( alignment: Alignment.centerRight, builder: SwiperPagination.fraction), )) @@ -188,17 +211,19 @@ class ExampleFraction extends StatelessWidget { } class ExampleCustomPagination extends StatelessWidget { + const ExampleCustomPagination({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("Custom Pagination"), + title: const Text('Custom Pagination'), ), body: Column( children: [ Expanded( child: Swiper( - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Image.asset( images[index], fit: BoxFit.fill, @@ -207,28 +232,25 @@ class ExampleCustomPagination extends StatelessWidget { autoplay: true, itemCount: images.length, pagination: SwiperPagination( - margin: EdgeInsets.all(0.0), - builder: SwiperCustomPagination(builder: - (BuildContext context, SwiperPluginConfig? config) { + margin: EdgeInsets.zero, + builder: SwiperCustomPagination(builder: (context, config) { return ConstrainedBox( child: Container( color: Colors.white, - child: config != null - ? Text( - "${titles[config.activeIndex!]} ${config.activeIndex! + 1}/${config.itemCount}", - style: TextStyle(fontSize: 20.0), - ) - : Offstage(), + child: Text( + '${titles[config.activeIndex]} ${config.activeIndex + 1}/${config.itemCount}', + style: const TextStyle(fontSize: 20.0), + ), ), - constraints: BoxConstraints.expand(height: 50.0), + constraints: const BoxConstraints.expand(height: 50.0), ); })), - control: SwiperControl(), + control: const SwiperControl(), ), ), Expanded( child: Swiper( - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Image.asset( images[index], fit: BoxFit.fill, @@ -237,21 +259,19 @@ class ExampleCustomPagination extends StatelessWidget { autoplay: true, itemCount: images.length, pagination: SwiperPagination( - margin: EdgeInsets.all(0.0), - builder: SwiperCustomPagination(builder: - (BuildContext context, SwiperPluginConfig? config) { + margin: EdgeInsets.zero, + builder: SwiperCustomPagination(builder: (context, config) { return ConstrainedBox( child: Row( children: [ - if (config != null) - Text( - "${titles[config.activeIndex!]} ${config.activeIndex! + 1}/${config.itemCount}", - style: TextStyle(fontSize: 20.0), - ), + Text( + '${titles[config.activeIndex]} ${config.activeIndex + 1}/${config.itemCount}', + style: const TextStyle(fontSize: 20.0), + ), Expanded( child: Align( alignment: Alignment.centerRight, - child: DotSwiperPaginationBuilder( + child: const DotSwiperPaginationBuilder( color: Colors.black12, activeColor: Colors.black, size: 10.0, @@ -261,10 +281,10 @@ class ExampleCustomPagination extends StatelessWidget { ) ], ), - constraints: BoxConstraints.expand(height: 50.0), + constraints: const BoxConstraints.expand(height: 50.0), ); })), - control: SwiperControl(color: Colors.redAccent), + control: const SwiperControl(color: Colors.redAccent), ), ) ], @@ -273,24 +293,26 @@ class ExampleCustomPagination extends StatelessWidget { } class ExamplePhone extends StatelessWidget { + const ExamplePhone({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text("Phone"), + title: const Text('Phone'), ), body: Stack( children: [ ConstrainedBox( - constraints: BoxConstraints.expand(), + constraints: const BoxConstraints.expand(), child: Image.asset( - "images/bg.jpeg", + 'images/bg.jpeg', fit: BoxFit.fill, ), ), Swiper.children( autoplay: false, - pagination: SwiperPagination( + pagination: const SwiperPagination( margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 30.0), builder: DotSwiperPaginationBuilder( color: Colors.white30, @@ -299,14 +321,14 @@ class ExamplePhone extends StatelessWidget { activeSize: 20.0)), children: [ Image.asset( - "images/1.png", + 'images/1.png', fit: BoxFit.contain, ), Image.asset( - "images/2.png", + 'images/2.png', fit: BoxFit.contain, ), - Image.asset("images/3.png", fit: BoxFit.contain) + Image.asset('images/3.png', fit: BoxFit.contain) ], ) ], @@ -320,7 +342,12 @@ class ScaffoldWidget extends StatelessWidget { final String title; final List? actions; - ScaffoldWidget({required this.child, required this.title, this.actions}); + const ScaffoldWidget({ + Key? key, + required this.title, + required this.child, + this.actions, + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/example/lib/src/ExampleCustom.dart b/example/lib/src/ExampleCustom.dart deleted file mode 100644 index c98c8fb..0000000 --- a/example/lib/src/ExampleCustom.dart +++ /dev/null @@ -1,335 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:card_swiper/card_swiper.dart'; -import 'config.dart'; -import 'forms/form_widget.dart'; - -class ExampleCustom extends StatefulWidget { - @override - State createState() { - return _ExampleCustomState(); - } -} - -class _ExampleCustomState extends State { - //properties want to custom - late int _itemCount; - - late bool _loop; - - late bool _autoplay; - - late int _autoplayDelay; - - late double _padding; - - late bool _outer; - - late double _radius; - - late double _viewportFraction; - - late SwiperLayout _layout; - - late int _currentIndex; - - late double _scale; - - late Axis _scrollDirection; - - late Curve _curve; - - late double _fade; - - late bool _autoplayDisableOnInteraction; - - late CustomLayoutOption customLayoutOption; - - late SwiperController _controller; - - TextEditingController numberController = TextEditingController(); - - Widget _buildItem(BuildContext context, int index) { - return ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(_radius)), - child: Image.asset( - images[index % images.length], - fit: BoxFit.fill, - ), - ); - } - - @override - void didUpdateWidget(ExampleCustom oldWidget) { - customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3) - .addRotate([-45.0 / 180, 0.0, 45.0 / 180]).addTranslate( - [Offset(-370.0, -40.0), Offset(0.0, 0.0), Offset(370.0, -40.0)]); - super.didUpdateWidget(oldWidget); - } - - @override - void initState() { - customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3) - .addRotate([-25.0 / 180, 0.0, 25.0 / 180]).addTranslate( - [Offset(-350.0, 0.0), Offset(0.0, 0.0), Offset(350.0, 0.0)]); - _fade = 1.0; - _currentIndex = 0; - _curve = Curves.ease; - _scale = 0.8; - _controller = SwiperController(); - _layout = SwiperLayout.TINDER; - _radius = 10.0; - _padding = 0.0; - _loop = true; - _itemCount = 3; - _autoplay = false; - _autoplayDelay = 3000; - _viewportFraction = 0.8; - _outer = false; - _scrollDirection = Axis.horizontal; - _autoplayDisableOnInteraction = false; - super.initState(); - } - -// maintain the index - - Widget buildSwiper() { - return Swiper( - onTap: (int index) { - Navigator.of(context) - .push(MaterialPageRoute(builder: (BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text('New page'), - ), - body: Container(), - ); - })); - }, - customLayoutOption: customLayoutOption, - fade: _fade, - index: _currentIndex, - onIndexChanged: (int index) { - setState(() { - _currentIndex = index; - }); - }, - curve: _curve, - scale: _scale, - itemWidth: 300.0, - controller: _controller, - layout: _layout, - outer: _outer, - itemHeight: 200.0, - viewportFraction: _viewportFraction, - autoplayDelay: _autoplayDelay, - loop: _loop, - autoplay: _autoplay, - itemBuilder: _buildItem, - itemCount: _itemCount, - scrollDirection: _scrollDirection, - indicatorLayout: PageIndicatorLayout.COLOR, - autoplayDisableOnInteraction: _autoplayDisableOnInteraction, - pagination: SwiperPagination( - builder: const DotSwiperPaginationBuilder( - size: 20.0, activeSize: 20.0, space: 10.0)), - ); - } - - @override - Widget build(BuildContext context) { - return Column(children: [ - Container( - color: Colors.black87, - child: SizedBox( - height: 300.0, width: double.infinity, child: buildSwiper()), - ), - Expanded( - child: ListView( - children: [ - Text('Index:$_currentIndex'), - Row( - children: [ - ElevatedButton( - onPressed: () { - _controller.previous(animation: true); - }, - child: Text('Prev'), - ), - ElevatedButton( - onPressed: () { - _controller.next(animation: true); - }, - child: Text('Next'), - ), - Expanded( - child: TextField( - controller: numberController, - )), - ElevatedButton( - onPressed: () { - var text = numberController.text; - setState(() { - _currentIndex = int.parse(text); - }); - }, - child: Text('Update'), - ), - ], - ), - FormWidget( - label: 'layout', - child: FormSelect( - placeholder: 'Select layout', - value: _layout, - values: [ - SwiperLayout.DEFAULT, - SwiperLayout.STACK, - SwiperLayout.TINDER, - SwiperLayout.CUSTOM - ], - valueChanged: (SwiperLayout value) { - _layout = value; - setState(() {}); - }, - ), - ), - FormWidget( - label: 'scrollDirection', - child: Switch( - value: _scrollDirection == Axis.horizontal, - onChanged: (bool value) => setState(() => _scrollDirection = - value ? Axis.horizontal : Axis.vertical)), - ), - FormWidget( - label: 'autoplayDisableOnInteraction', - child: Switch( - value: _autoplayDisableOnInteraction, - onChanged: (bool value) => - setState(() => _autoplayDisableOnInteraction = value)), - ), - //Pannel Begin - FormWidget( - label: 'loop', - child: Switch( - value: _loop, - onChanged: (bool value) => setState(() => _loop = value)), - ), - FormWidget( - label: 'outer', - child: Switch( - value: _outer, - onChanged: (bool value) => setState(() => _outer = value)), - ), - //Pannel Begin - FormWidget( - label: 'autoplay', - child: Switch( - value: _autoplay, - onChanged: (bool value) => setState(() => _autoplay = value)), - ), - - FormWidget( - label: 'padding', - child: NumberPad( - number: _padding, - step: 5.0, - min: 0.0, - max: 30.0, - onChangeValue: (num value) { - _padding = value.toDouble(); - setState(() {}); - }, - ), - ), - FormWidget( - label: 'scale', - child: NumberPad( - number: _scale, - step: 0.1, - min: 0.0, - max: 1.0, - onChangeValue: (num value) { - _scale = value.toDouble(); - setState(() {}); - }, - ), - ), - FormWidget( - label: 'fade', - child: NumberPad( - number: _fade, - step: 0.1, - min: 0.0, - max: 1.0, - onChangeValue: (num value) { - _fade = value.toDouble(); - setState(() {}); - }, - ), - ), - FormWidget( - label: 'itemCount', - child: NumberPad( - number: _itemCount, - step: 1, - min: 0, - max: 100, - onChangeValue: (num value) { - _itemCount = value.toInt(); - setState(() {}); - }, - ), - ), - - FormWidget( - label: 'radius', - child: NumberPad( - number: _radius, - step: 1.0, - min: 0.0, - max: 30.0, - onChangeValue: (num value) { - this._radius = value.toDouble(); - setState(() {}); - }, - ), - ), - - FormWidget( - label: 'viewportFraction', - child: NumberPad( - number: _viewportFraction, - step: 0.1, - max: 1.0, - min: 0.5, - onChangeValue: (num value) { - _viewportFraction = value.toDouble(); - setState(() {}); - }, - ), - ), - - FormWidget( - label: 'curve', - child: FormSelect( - placeholder: 'Select curve', - value: _layout, - values: [ - Curves.easeInOut, - Curves.ease, - Curves.bounceInOut, - Curves.bounceOut, - Curves.bounceIn, - Curves.fastOutSlowIn - ], - valueChanged: (Curve value) { - _curve = value; - setState(() {}); - }, - ), - ), - ], - )) - ]); - } -} diff --git a/example/lib/src/config.dart b/example/lib/src/config.dart index fcea172..01b7518 100644 --- a/example/lib/src/config.dart +++ b/example/lib/src/config.dart @@ -1,5 +1,5 @@ -const List images = [ - "images/bg0.jpeg", - "images/bg1.jpeg", - "images/bg2.jpeg", +const images = [ + 'images/bg0.jpeg', + 'images/bg1.jpeg', + 'images/bg2.jpeg', ]; diff --git a/example/lib/src/example_custom.dart b/example/lib/src/example_custom.dart new file mode 100644 index 0000000..6f080a4 --- /dev/null +++ b/example/lib/src/example_custom.dart @@ -0,0 +1,357 @@ +import 'package:card_swiper/card_swiper.dart'; +import 'package:flutter/material.dart'; + +import 'config.dart'; +import 'forms/form_widget.dart'; + +class ExampleCustom extends StatefulWidget { + const ExampleCustom({Key? key}) : super(key: key); + + @override + State createState() { + return _ExampleCustomState(); + } +} + +class _ExampleCustomState extends State { + //properties want to custom + late int _itemCount; + + late bool _loop; + + late bool _autoplay; + + late int _autoplayDelay; + + late double _padding; + + late bool _outer; + + late double _radius; + + late double _viewportFraction; + + late SwiperLayout _layout; + + late int _currentIndex; + + late double _scale; + + late Axis _scrollDirection; + + late Curve _curve; + + late double _fade; + + late bool _autoplayDisableOnInteraction; + + late CustomLayoutOption customLayoutOption; + + late SwiperController _controller; + + TextEditingController numberController = TextEditingController(); + + Widget _buildItem(BuildContext context, int index) { + return ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(_radius)), + child: Image.asset( + images[index % images.length], + fit: BoxFit.fill, + ), + ); + } + + @override + void didUpdateWidget(ExampleCustom oldWidget) { + customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3) + ..addRotate([-45.0 / 180, 0.0, 45.0 / 180]) + ..addTranslate( + [ + const Offset(-370.0, -40.0), + Offset.zero, + const Offset(370.0, -40.0), + ], + ); + super.didUpdateWidget(oldWidget); + } + + @override + void initState() { + customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3) + ..addRotate([-25.0 / 180, 0.0, 25.0 / 180]) + ..addTranslate( + [ + const Offset(-350.0, 0.0), + Offset.zero, + const Offset(350.0, 0.0), + ], + ); + _fade = 1.0; + _currentIndex = 0; + _curve = Curves.ease; + _scale = 0.8; + _autoplay = false; + _controller = SwiperController(); + _layout = SwiperLayout.TINDER; + _radius = 10.0; + _padding = 0.0; + _loop = true; + _itemCount = 3; + _autoplayDelay = 3000; + _viewportFraction = 0.8; + _outer = false; + _scrollDirection = Axis.horizontal; + _autoplayDisableOnInteraction = false; + super.initState(); + } + +// maintain the index + + Widget buildSwiper() { + return Swiper( + onTap: (index) { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) { + return Scaffold( + appBar: AppBar( + title: const Text('New page'), + ), + body: Container(), + ); + }, + )); + }, + customLayoutOption: customLayoutOption, + fade: _fade, + index: _currentIndex, + onIndexChanged: (index) { + setState(() { + _currentIndex = index; + }); + }, + curve: _curve, + scale: _scale, + itemWidth: 300.0, + controller: _controller, + layout: _layout, + outer: _outer, + itemHeight: 200.0, + viewportFraction: _viewportFraction, + autoplayDelay: _autoplayDelay, + loop: _loop, + autoplay: _autoplay, + itemBuilder: _buildItem, + itemCount: _itemCount, + scrollDirection: _scrollDirection, + indicatorLayout: PageIndicatorLayout.COLOR, + autoplayDisableOnInteraction: _autoplayDisableOnInteraction, + pagination: const SwiperPagination( + builder: DotSwiperPaginationBuilder( + size: 20.0, activeSize: 20.0, space: 10.0)), + ); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + color: Colors.black87, + child: SizedBox( + height: 300.0, + width: double.infinity, + child: buildSwiper(), + ), + ), + Expanded( + child: ListView( + children: [ + Text('Index:$_currentIndex'), + Row( + children: [ + ElevatedButton( + onPressed: () { + _controller.previous(animation: true); + }, + child: const Text('Prev'), + ), + ElevatedButton( + onPressed: () { + _controller.next(animation: true); + }, + child: const Text('Next'), + ), + Expanded( + child: TextField( + controller: numberController, + )), + ElevatedButton( + onPressed: () { + final text = numberController.text; + setState(() { + _currentIndex = int.parse(text); + }); + }, + child: const Text('Update'), + ), + ], + ), + FormWidget( + label: 'layout', + child: FormSelect( + placeholder: 'Select layout', + value: _layout, + values: const [ + SwiperLayout.DEFAULT, + SwiperLayout.STACK, + SwiperLayout.TINDER, + SwiperLayout.CUSTOM + ], + valueChanged: (value) { + _layout = value; + setState(() {}); + }, + ), + ), + FormWidget( + label: 'scrollDirection', + child: Switch( + value: _scrollDirection == Axis.horizontal, + onChanged: (value) => setState(() => _scrollDirection = + value ? Axis.horizontal : Axis.vertical)), + ), + FormWidget( + label: 'autoplayDisableOnInteraction', + child: Switch( + value: _autoplayDisableOnInteraction, + onChanged: (value) => + setState(() => _autoplayDisableOnInteraction = value)), + ), + //Pannel Begin + FormWidget( + label: 'loop', + child: Switch( + value: _loop, + onChanged: (value) => setState(() => _loop = value)), + ), + FormWidget( + label: 'outer', + child: Switch( + value: _outer, + onChanged: (value) => setState(() => _outer = value)), + ), + //Pannel Begin + FormWidget( + label: 'autoplay', + child: Switch( + value: _autoplay, + onChanged: (value) => setState(() => _autoplay = value)), + ), + + FormWidget( + label: 'padding', + child: NumberPad( + number: _padding, + step: 5.0, + min: 0.0, + max: 30.0, + onChangeValue: (value) { + _padding = value.toDouble(); + setState(() {}); + }, + ), + ), + FormWidget( + label: 'scale', + child: NumberPad( + number: _scale, + step: 0.1, + min: 0.0, + max: 1.0, + onChangeValue: (value) { + _scale = value.toDouble(); + setState(() {}); + }, + ), + ), + FormWidget( + label: 'fade', + child: NumberPad( + number: _fade, + step: 0.1, + min: 0.0, + max: 1.0, + onChangeValue: (value) { + _fade = value.toDouble(); + setState(() {}); + }, + ), + ), + FormWidget( + label: 'itemCount', + child: NumberPad( + number: _itemCount, + step: 1, + min: 0, + max: 100, + onChangeValue: (value) { + _itemCount = value.toInt(); + setState(() {}); + }, + ), + ), + + FormWidget( + label: 'radius', + child: NumberPad( + number: _radius, + step: 1.0, + min: 0.0, + max: 30.0, + onChangeValue: (value) { + _radius = value.toDouble(); + setState(() {}); + }, + ), + ), + + FormWidget( + label: 'viewportFraction', + child: NumberPad( + number: _viewportFraction, + step: 0.1, + max: 1.0, + min: 0.5, + onChangeValue: (value) { + _viewportFraction = value.toDouble(); + setState(() {}); + }, + ), + ), + + FormWidget( + label: 'curve', + child: FormSelect( + placeholder: 'Select curve', + value: _curve, + values: const [ + Curves.easeInOut, + Curves.ease, + Curves.bounceInOut, + Curves.bounceOut, + Curves.bounceIn, + Curves.fastOutSlowIn + ], + valueChanged: (value) { + _curve = value; + setState(() {}); + }, + ), + ), + ], + ), + ) + ], + ); + } +} diff --git a/example/lib/src/ExampleSwiperInScrollView.dart b/example/lib/src/example_swiper_in_scrollview.dart similarity index 85% rename from example/lib/src/ExampleSwiperInScrollView.dart rename to example/lib/src/example_swiper_in_scrollview.dart index 3c615ca..557e5e4 100644 --- a/example/lib/src/ExampleSwiperInScrollView.dart +++ b/example/lib/src/example_swiper_in_scrollview.dart @@ -1,7 +1,9 @@ -import 'package:flutter/material.dart'; import 'package:card_swiper/card_swiper.dart'; +import 'package:flutter/material.dart'; class ExampleSwiperInScrollView extends StatefulWidget { + const ExampleSwiperInScrollView({Key? key}) : super(key: key); + @override State createState() { return _ExampleState(); @@ -32,7 +34,7 @@ class _ExampleState extends State _animation11 = Tween(begin: 0.0, end: 1.0).animate(controller); _animation12 = Tween(begin: 0.0, end: 1.0).animate(controller); _animation13 = Tween(begin: 0.0, end: 1.0).animate(controller); - controller.animateTo(1.0, duration: Duration(seconds: 3)); + controller.animateTo(1.0, duration: const Duration(seconds: 3)); super.initState(); } @@ -135,7 +137,7 @@ class _ExampleState extends State ); }, itemCount: 10, - pagination: SwiperPagination(), + pagination: const SwiperPagination(), ), ), SizedBox( @@ -149,8 +151,8 @@ class _ExampleState extends State child: Text('$i'), ); }, - pagination: - SwiperPagination(builder: SwiperPagination.fraction), + pagination: const SwiperPagination( + builder: SwiperPagination.fraction), itemCount: 0), ), SizedBox( @@ -164,8 +166,8 @@ class _ExampleState extends State child: Text('$i'), ); }, - pagination: - SwiperPagination(builder: SwiperPagination.fraction), + pagination: const SwiperPagination( + builder: SwiperPagination.fraction), itemCount: 10000), ), SizedBox( @@ -180,15 +182,15 @@ class _ExampleState extends State child: Text('$i'), ); }, - pagination: SwiperPagination(), + pagination: const SwiperPagination(), itemCount: 10), ), - Text('Image from network'), + const Text('Image from network'), SizedBox( height: 300.0, child: Swiper( itemCount: 10, - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return Image.network( 'https://ss3.baidu.com/9fo3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=87d6daed02f41bd5c553eef461d881a0/f9198618367adab4b025268587d4b31c8601e47b.jpg'); }, @@ -206,14 +208,12 @@ class _ExampleState extends State child: Stack( alignment: AlignmentDirectional.center, children: [ - Container( - child: Image.network( - 'https://ss3.baidu.com/9fo3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=87d6daed02f41bd5c553eef461d881a0/f9198618367adab4b025268587d4b31c8601e47b.jpg'), - ), + Image.network( + 'https://ss3.baidu.com/9fo3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=87d6daed02f41bd5c553eef461d881a0/f9198618367adab4b025268587d4b31c8601e47b.jpg'), FractionalTranslation( - translation: Offset(0.0, 0.0), + translation: Offset.zero, child: Container( - alignment: FractionalOffset(0.0, 0.0), + alignment: FractionalOffset.topLeft, decoration: BoxDecoration( border: Border.all( color: Colors.lightBlue.withOpacity(0.5), @@ -225,17 +225,17 @@ class _ExampleState extends State ), Container( //padding: const EdgeInsets.only(bottom:10.0), - margin: EdgeInsets.all(140.0), + margin: const EdgeInsets.all(140.0), - child: Icon(Icons.location_on, + child: const Icon(Icons.location_on, color: Colors.white, size: 25.0), ), ], ), ); }, - pagination: - SwiperPagination(alignment: Alignment.topCenter), + pagination: const SwiperPagination( + alignment: Alignment.topCenter), itemCount: 10), ), SizedBox( @@ -245,8 +245,8 @@ class _ExampleState extends State itemBuilder: (c, i) { return _buildDynamicCard(); }, - pagination: - SwiperPagination(alignment: Alignment.topCenter), + pagination: const SwiperPagination( + alignment: Alignment.topCenter), itemCount: 10), ), SizedBox( @@ -262,8 +262,8 @@ class _ExampleState extends State child: Text('$i'), ); }, - pagination: - SwiperPagination(alignment: Alignment.topCenter), + pagination: const SwiperPagination( + alignment: Alignment.topCenter), itemCount: 10), ), ], diff --git a/example/lib/src/forms/form_widget.dart b/example/lib/src/forms/form_widget.dart index e7af9cb..4bd99a7 100644 --- a/example/lib/src/forms/form_widget.dart +++ b/example/lib/src/forms/form_widget.dart @@ -1,23 +1,24 @@ -import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; class FormWidget extends StatelessWidget { final String label; final Widget child; - FormWidget({ + const FormWidget({ + Key? key, required this.label, required this.child, - }); + }) : super(key: key); @override Widget build(BuildContext context) { return Padding( - padding: EdgeInsets.all(5.0), + padding: const EdgeInsets.all(5.0), child: Row( children: [ - Text(label, style: TextStyle(fontSize: 14.0)), + Text(label, style: const TextStyle(fontSize: 14.0)), Expanded( child: Align( alignment: Alignment.centerRight, @@ -33,28 +34,29 @@ class FormWidget extends StatelessWidget { class FormSelect extends StatefulWidget { final String placeholder; final ValueChanged valueChanged; - final List values; - final Object value; + final List values; + final T value; - FormSelect({ + const FormSelect({ + Key? key, required this.placeholder, required this.valueChanged, required this.value, required this.values, - }); + }) : super(key: key); @override State createState() { - return _FormSelectState(); + return _FormSelectState(); } } -class _FormSelectState extends State { +class _FormSelectState extends State> { int _selectedIndex = 0; @override void initState() { - for (int i = 0, c = widget.values.length; i < c; ++i) { + for (var i = 0; i < widget.values.length; ++i) { if (widget.values[i] == widget.value) { _selectedIndex = i; break; @@ -66,58 +68,55 @@ class _FormSelectState extends State { @override Widget build(BuildContext context) { - String placeholder = widget.placeholder; - List values = widget.values; - - return Container( - child: InkWell( - child: Text(_selectedIndex < 0 - ? placeholder - : values[_selectedIndex].toString()), - onTap: () { - _selectedIndex = 0; - showBottomSheet( - context: context, - builder: (BuildContext context) { - return SizedBox( - height: values.length * 30.0 + 200.0, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: values.length * 30.0 + 70.0, - child: CupertinoPicker( - itemExtent: 30.0, - children: values.map((Object value) { - return Text(value.toString()); - }).toList(), - onSelectedItemChanged: (int index) { - _selectedIndex = index; - }, - ), + final placeholder = widget.placeholder; + final values = widget.values; + + return InkWell( + child: Text( + _selectedIndex < 0 ? placeholder : values[_selectedIndex].toString()), + onTap: () { + _selectedIndex = 0; + showBottomSheet( + context: context, + builder: (context) { + return SizedBox( + height: values.length * 30.0 + 200.0, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: values.length * 30.0 + 70.0, + child: CupertinoPicker( + itemExtent: 30.0, + children: values.map((value) { + return Text(value.toString()); + }).toList(), + onSelectedItemChanged: (index) { + _selectedIndex = index; + }, ), - Center( - child: ElevatedButton( - onPressed: () { - if (_selectedIndex >= 0) { - widget.valueChanged( - widget.values[_selectedIndex], - ); - } - - setState(() {}); - - Navigator.of(context).pop(); - }, - child: Text('ok'), - ), - ) - ], - ), - ); - }); - }, - ), + ), + Center( + child: ElevatedButton( + onPressed: () { + if (_selectedIndex >= 0) { + widget.valueChanged( + widget.values[_selectedIndex], + ); + } + + setState(() {}); + + Navigator.of(context).pop(); + }, + child: const Text('ok'), + ), + ) + ], + ), + ); + }); + }, ); } } @@ -129,13 +128,14 @@ class NumberPad extends StatelessWidget { final num min; final ValueChanged onChangeValue; - NumberPad({ + const NumberPad({ + Key? key, required this.number, required this.step, required this.onChangeValue, required this.max, required this.min, - }); + }) : super(key: key); void onAdd() { onChangeValue(number + step > max ? max : number + step); @@ -150,12 +150,12 @@ class NumberPad extends StatelessWidget { return Row( mainAxisSize: MainAxisSize.min, children: [ - IconButton(icon: Icon(Icons.exposure_neg_1), onPressed: onSub), + IconButton(icon: const Icon(Icons.exposure_neg_1), onPressed: onSub), Text( number is int ? number.toString() : number.toStringAsFixed(1), - style: TextStyle(fontSize: 14.0), + style: const TextStyle(fontSize: 14.0), ), - IconButton(icon: Icon(Icons.exposure_plus_1), onPressed: onAdd) + IconButton(icon: const Icon(Icons.exposure_plus_1), onPressed: onAdd) ], ); } diff --git a/example/pubspec.lock b/example/pubspec.lock index 2f25a98..8b8e467 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,21 +21,21 @@ packages: path: ".." relative: true source: path - version: "1.0.3" + version: "2.0.0" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" clock: dependency: transitive description: @@ -69,25 +69,46 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: transitive + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_lints_plus: + dependency: "direct dev" + description: + name: flutter_lints_plus + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" path: dependency: transitive description: @@ -141,7 +162,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.3" typed_data: dependency: transitive description: @@ -155,7 +176,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=0.1.4" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 4770d65..0985fcf 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -19,6 +19,7 @@ dependencies: path: ../ dev_dependencies: + flutter_lints_plus: ^1.0.1 flutter_test: sdk: flutter diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 747db1d..5047a3c 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -5,15 +5,14 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. +import 'package:example/main.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:example/main.dart'; - void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { + testWidgets('Counter increments smoke test', (tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + await tester.pumpWidget(const MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); diff --git a/lib/card_swiper.dart b/lib/card_swiper.dart index bb8ea17..db43602 100644 --- a/lib/card_swiper.dart +++ b/lib/card_swiper.dart @@ -1,9 +1,9 @@ library card_swiper; +export 'src/flutter_page_indicator/flutter_page_indicator.dart'; export 'src/swiper.dart'; -export 'src/swiper_pagination.dart'; export 'src/swiper_control.dart'; export 'src/swiper_controller.dart'; +export 'src/swiper_pagination.dart'; export 'src/swiper_plugin.dart'; -export 'src/flutter_page_indicator/flutter_page_indicator.dart'; export 'src/transformer_page_view/index_controller.dart'; diff --git a/lib/src/custom_layout.dart b/lib/src/custom_layout.dart index d2c4c12..f6fade6 100644 --- a/lib/src/custom_layout.dart +++ b/lib/src/custom_layout.dart @@ -2,10 +2,11 @@ part of 'swiper.dart'; abstract class _CustomLayoutStateBase extends State with SingleTickerProviderStateMixin { - double? _swiperWidth; - double? _swiperHeight; + late double _swiperWidth; + late double _swiperHeight; late Animation _animation; - AnimationController? _animationController; + late AnimationController _animationController; + SwiperController get _controller => widget.controller; late int _startIndex; int? _animationCount; int _currentIndex = 0; @@ -20,14 +21,14 @@ abstract class _CustomLayoutStateBase extends State } _createAnimationController(); - widget.controller!.addListener(_onController); + _controller.addListener(_onController); super.initState(); } void _createAnimationController() { _animationController = AnimationController(vsync: this, value: 0.5); final tween = Tween(begin: 0.0, end: 1.0); - _animation = tween.animate(_animationController!); + _animation = tween.animate(_animationController); } @override @@ -36,7 +37,7 @@ abstract class _CustomLayoutStateBase extends State super.didChangeDependencies(); } - void _getSize(_) { + void _getSize(Duration _) { afterRender(); } @@ -52,12 +53,12 @@ abstract class _CustomLayoutStateBase extends State @override void didUpdateWidget(T oldWidget) { if (widget.controller != oldWidget.controller) { - oldWidget.controller!.removeListener(_onController); - widget.controller!.addListener(_onController); + oldWidget.controller.removeListener(_onController); + widget.controller.addListener(_onController); } if (widget.loop != oldWidget.loop) { - if (!widget.loop!) { + if (!widget.loop) { _currentIndex = _ensureIndex(_currentIndex); } } @@ -66,17 +67,18 @@ abstract class _CustomLayoutStateBase extends State } int _ensureIndex(int index) { - index = index % widget.itemCount!; - if (index < 0) { - index += widget.itemCount!; + var res = index; + res = index % widget.itemCount; + if (res < 0) { + res += widget.itemCount; } - return index; + return res; } @override void dispose() { - widget.controller!.removeListener(_onController); - _animationController?.dispose(); + widget.controller.removeListener(_onController); + _animationController.dispose(); super.dispose(); } @@ -89,15 +91,15 @@ abstract class _CustomLayoutStateBase extends State } Widget _buildAnimation(BuildContext context, Widget? w) { - var list = []; + final list = []; final animationValue = _animation.value; for (var i = 0; i < _animationCount!; ++i) { var realIndex = _currentIndex + i + _startIndex; - realIndex = realIndex % widget.itemCount!; + realIndex = realIndex % widget.itemCount; if (realIndex < 0) { - realIndex += widget.itemCount!; + realIndex += widget.itemCount; } list.add(_buildItem(i, realIndex, animationValue)); @@ -122,7 +124,9 @@ abstract class _CustomLayoutStateBase extends State return Container(); } return AnimatedBuilder( - animation: _animationController!, builder: _buildAnimation); + animation: _animationController, + builder: _buildAnimation, + ); } late double _currentValue; @@ -130,78 +134,63 @@ abstract class _CustomLayoutStateBase extends State bool _lockScroll = false; - void _move(double position, {int? nextIndex}) async { + Future _move(double position, {int? nextIndex}) async { if (_lockScroll) return; try { _lockScroll = true; - await _animationController!.animateTo(position, - duration: Duration(milliseconds: widget.duration!), - curve: widget.curve!); + await _animationController.animateTo( + position, + duration: Duration(milliseconds: widget.duration!), + curve: widget.curve, + ); if (nextIndex != null) { widget.onIndexChanged!(widget.getCorrectIndex(nextIndex)); } - } catch (e) { - print(e); + } catch (e, st) { + log('error animating _animationController', error: e, stackTrace: st); } finally { if (nextIndex != null) { try { - _animationController!.value = 0.5; - } catch (e) { - print(e); + _animationController.value = 0.5; + } catch (e, st) { + log( + 'error setting _animationController.value', + error: e, + stackTrace: st, + ); } - _currentIndex = nextIndex; } _lockScroll = false; } } - int _nextIndex() { - final index = _currentIndex + 1; - if (!widget.loop! && index >= widget.itemCount! - 1) { - return widget.itemCount! - 1; - } - return index; - } - - int _moveIndex() { - final index = widget.controller!.index ?? _currentIndex; - if(!widget.loop! && index >= widget.itemCount! - 1) { - return widget.itemCount! - 1; - } else if(!widget.loop! && index < 0) { - return 0; + int _getProperNewIndex(int newIndex) { + var res = newIndex; + if (!widget.loop && newIndex >= widget.itemCount - 1) { + res = widget.itemCount - 1; + } else if (!widget.loop && newIndex < 0) { + res = 0; } - return index; - } - - int _prevIndex() { - final index = _currentIndex - 1; - if (!widget.loop! && index < 0) { - return 0; - } - return index; + return res; } void _onController() { - switch (widget.controller!.event) { - case IndexController.PREVIOUS: - final prevIndex = _prevIndex(); - if (prevIndex == _currentIndex) return; - _move(1.0, nextIndex: prevIndex); - break; - case IndexController.NEXT: - final nextIndex = _nextIndex(); - if (nextIndex == _currentIndex) return; - _move(0.0, nextIndex: nextIndex); - break; - case IndexController.MOVE: - var moveIndex = _moveIndex(); - if (moveIndex == _currentIndex) return; - _move(moveIndex > _currentIndex ? 1.0 : 0.0, nextIndex: moveIndex); - break; - case SwiperController.STOP_AUTOPLAY: - case SwiperController.START_AUTOPLAY: - break; + final controller = widget.controller; + final event = controller.event; + if (event is StepBasedIndexControllerEvent) { + final newIndex = event.calcNextIndex( + currentIndex: _currentIndex, + itemCount: widget.itemCount, + loop: widget.loop, + reverse: false, + ); + _move(event.targetPosition, nextIndex: newIndex); + } else if (event is MoveIndexControllerEvent) { + _move( + event.targetPosition, + nextIndex: _getProperNewIndex(event.newIndex), + ); } } @@ -212,13 +201,13 @@ abstract class _CustomLayoutStateBase extends State ? details.velocity.pixelsPerSecond.dx : details.velocity.pixelsPerSecond.dy; - if (_animationController!.value >= 0.75 || velocity > 500.0) { - if (_currentIndex <= 0 && !widget.loop!) { + if (_animationController.value >= 0.75 || velocity > 500.0) { + if (_currentIndex <= 0 && !widget.loop) { return; } _move(1.0, nextIndex: _currentIndex - 1); - } else if (_animationController!.value < 0.25 || velocity < -500.0) { - if (_currentIndex >= widget.itemCount! - 1 && !widget.loop!) { + } else if (_animationController.value < 0.25 || velocity < -500.0) { + if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { return; } _move(0.0, nextIndex: _currentIndex + 1); @@ -229,7 +218,7 @@ abstract class _CustomLayoutStateBase extends State void _onPanStart(DragStartDetails details) { if (_lockScroll) return; - _currentValue = _animationController!.value; + _currentValue = _animationController.value; _currentPos = widget.scrollDirection == Axis.horizontal ? details.globalPosition.dx : details.globalPosition.dy; @@ -242,11 +231,11 @@ abstract class _CustomLayoutStateBase extends State ? details.globalPosition.dx : details.globalPosition.dy) - _currentPos) / - _swiperWidth! / + _swiperWidth / 2; // no loop ? - if (!widget.loop!) { - if (_currentIndex >= widget.itemCount! - 1) { + if (!widget.loop) { + if (_currentIndex >= widget.itemCount - 1) { if (value < 0.5) { value = 0.5; } @@ -257,19 +246,19 @@ abstract class _CustomLayoutStateBase extends State } } - _animationController!.value = value; + _animationController.value = value; } } -double? _getValue(List values, double animationValue, int index) { +double _getValue(List values, double animationValue, int index) { var s = values[index]; if (animationValue >= 0.5) { if (index < values.length - 1) { - s = s! + (values[index + 1]! - s) * (animationValue - 0.5) * 2.0; + s = s + (values[index + 1] - s) * (animationValue - 0.5) * 2.0; } } else { if (index != 0) { - s = s! - (s - values[index - 1]!) * (0.5 - animationValue) * 2.0; + s = s - (s - values[index - 1]) * (0.5 - animationValue) * 2.0; } } return s; @@ -294,9 +283,9 @@ Offset _getOffsetValue(List values, double animationValue, int index) { } abstract class TransformBuilder { - List? values; + final List values; - TransformBuilder({this.values}); + TransformBuilder({required this.values}); Widget build(int i, double animationValue, Widget widget); } @@ -304,23 +293,25 @@ abstract class TransformBuilder { class ScaleTransformBuilder extends TransformBuilder { final Alignment alignment; - ScaleTransformBuilder( - {List? values, this.alignment = Alignment.center}) - : super(values: values); + ScaleTransformBuilder({ + required List values, + this.alignment = Alignment.center, + }) : super(values: values); @override Widget build(int i, double animationValue, Widget widget) { - final s = _getValue(values!, animationValue, i)!; + final s = _getValue(values, animationValue, i); return Transform.scale(scale: s, child: widget); } } class OpacityTransformBuilder extends TransformBuilder { - OpacityTransformBuilder({List? values}) : super(values: values); + OpacityTransformBuilder({required List values}) + : super(values: values); @override Widget build(int i, double animationValue, Widget widget) { - final v = _getValue(values!, animationValue, i)!; + final v = _getValue(values, animationValue, i); return Opacity( opacity: v, child: widget, @@ -329,11 +320,12 @@ class OpacityTransformBuilder extends TransformBuilder { } class RotateTransformBuilder extends TransformBuilder { - RotateTransformBuilder({List? values}) : super(values: values); + RotateTransformBuilder({required List values}) + : super(values: values); @override Widget build(int i, double animationValue, Widget widget) { - final v = _getValue(values!, animationValue, i)!; + final v = _getValue(values, animationValue, i); return Transform.rotate( angle: v, child: widget, @@ -342,11 +334,12 @@ class RotateTransformBuilder extends TransformBuilder { } class TranslateTransformBuilder extends TransformBuilder { - TranslateTransformBuilder({List? values}) : super(values: values); + TranslateTransformBuilder({required List values}) + : super(values: values); @override Widget build(int i, double animationValue, Widget widget) { - final s = _getOffsetValue(values!, animationValue, i); + final s = _getOffsetValue(values, animationValue, i); return Transform.translate( offset: s, child: widget, @@ -361,44 +354,40 @@ class CustomLayoutOption { CustomLayoutOption({this.stateCount, required this.startIndex}); - CustomLayoutOption addOpacity(List values) { + void addOpacity(List values) { builders.add(OpacityTransformBuilder(values: values)); - return this; } - CustomLayoutOption addTranslate(List values) { + void addTranslate(List values) { builders.add(TranslateTransformBuilder(values: values)); - return this; } - CustomLayoutOption addScale(List values, Alignment alignment) { + void addScale(List values, Alignment alignment) { builders.add(ScaleTransformBuilder(values: values, alignment: alignment)); - return this; } - CustomLayoutOption addRotate(List values) { + void addRotate(List values) { builders.add(RotateTransformBuilder(values: values)); - return this; } } class _CustomLayoutSwiper extends _SubSwiper { final CustomLayoutOption option; - _CustomLayoutSwiper({ + const _CustomLayoutSwiper({ required this.option, double? itemWidth, - bool? loop, + required bool loop, double? itemHeight, ValueChanged? onIndexChanged, Key? key, IndexedWidgetBuilder? itemBuilder, - Curve? curve, + required Curve curve, int? duration, int? index, - int? itemCount, + required int itemCount, Axis? scrollDirection, - SwiperController? controller, + required SwiperController controller, }) : super( loop: loop, onIndexChanged: onIndexChanged, @@ -444,7 +433,7 @@ class _CustomLayoutState extends _CustomLayoutStateBase<_CustomLayoutSwiper> { child: widget.itemBuilder!(context, realIndex)); for (var i = builders.length - 1; i >= 0; --i) { - var builder = builders[i]; + final builder = builders[i]; child = builder.build(index, animationValue, child); } diff --git a/lib/src/flutter_page_indicator/flutter_page_indicator.dart b/lib/src/flutter_page_indicator/flutter_page_indicator.dart index 47d20d9..ef24839 100644 --- a/lib/src/flutter_page_indicator/flutter_page_indicator.dart +++ b/lib/src/flutter_page_indicator/flutter_page_indicator.dart @@ -1,7 +1,8 @@ +// ignore_for_file: constant_identifier_names + library flutter_page_indicator; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; class WarmPainter extends BasePainter { WarmPainter(PageIndicator widget, double page, int index, Paint paint) @@ -9,9 +10,9 @@ class WarmPainter extends BasePainter { @override void draw(Canvas canvas, double space, double size, double radius) { - var progress = page - index; - var distance = size + space; - var start = index * (size + space); + final progress = page - index; + final distance = size + space; + final start = index * (size + space); if (progress > 0.5) { final right = start + size + distance; @@ -88,13 +89,12 @@ class ScalePainter extends BasePainter { ScalePainter(PageIndicator widget, double page, int index, Paint paint) : super(widget, page, index, paint); - // 连续的两个点,含有最后一个和第一个 @override - bool _shouldSkip(int i) { - if (index == widget.count - 1) { - return i == 0 || i == index; + bool _shouldSkip(int index) { + if (this.index == widget.count - 1) { + return index == 0 || index == this.index; } - return (i == index || i == index + 1); + return (index == this.index || index == this.index + 1); } @override @@ -103,7 +103,8 @@ class ScalePainter extends BasePainter { final space = widget.space; final size = widget.size; final radius = size / 2; - for (var i = 0, c = widget.count; i < c; ++i) { + final c = widget.count; + for (var i = 0; i < c; ++i) { if (_shouldSkip(i)) { continue; } @@ -137,13 +138,12 @@ class ColorPainter extends BasePainter { ColorPainter(PageIndicator widget, double page, int index, Paint paint) : super(widget, page, index, paint); - // 连续的两个点,含有最后一个和第一个 @override - bool _shouldSkip(int i) { - if (index == widget.count - 1) { - return i == 0 || i == index; + bool _shouldSkip(int index) { + if (this.index == widget.count - 1) { + return index == 0 || index == this.index; } - return (i == index || i == index + 1); + return (index == this.index || index == this.index + 1); } @override @@ -189,7 +189,8 @@ abstract class BasePainter extends CustomPainter { final space = widget.space; final size = widget.size; final radius = size / 2; - for (var i = 0, c = widget.count; i < c; ++i) { + final c = widget.count; + for (var i = 0; i < c; ++i) { if (_shouldSkip(i)) { continue; } @@ -213,28 +214,23 @@ abstract class BasePainter extends CustomPainter { class _PageIndicatorState extends State { int index = 0; + double page = 0; final _paint = Paint(); BasePainter _createPainter() { switch (widget.layout) { case PageIndicatorLayout.NONE: - return NonePainter( - widget, widget.controller.page ?? 0.0, index, _paint); + return NonePainter(widget, page, index, _paint); case PageIndicatorLayout.SLIDE: - return SlidePainter( - widget, widget.controller.page ?? 0.0, index, _paint); + return SlidePainter(widget, page, index, _paint); case PageIndicatorLayout.WARM: - return WarmPainter( - widget, widget.controller.page ?? 0.0, index, _paint); + return WarmPainter(widget, page, index, _paint); case PageIndicatorLayout.COLOR: - return ColorPainter( - widget, widget.controller.page ?? 0.0, index, _paint); + return ColorPainter(widget, page, index, _paint); case PageIndicatorLayout.SCALE: - return ScalePainter( - widget, widget.controller.page ?? 0.0, index, _paint); + return ScalePainter(widget, page, index, _paint); case PageIndicatorLayout.DROP: - return DropPainter( - widget, widget.controller.page ?? 0.0, index, _paint); + return DropPainter(widget, page, index, _paint); default: throw Exception('Not a valid layout'); } @@ -262,26 +258,28 @@ class _PageIndicatorState extends State { ); } - void _onController() { - final page = widget.controller.page ?? 0.0; + void _onController([bool doSetState = true]) { + page = (widget.controller.hasClients ? widget.controller.page : 0) ?? 0.0; index = page.floor(); - - setState(() {}); + if (doSetState) { + setState(() {}); + } } @override void initState() { - widget.controller.addListener(_onController); super.initState(); + widget.controller.addListener(_onController); + _onController(false); } @override void didUpdateWidget(PageIndicator oldWidget) { + super.didUpdateWidget(oldWidget); if (widget.controller != oldWidget.controller) { oldWidget.controller.removeListener(_onController); widget.controller.addListener(_onController); } - super.didUpdateWidget(oldWidget); } @override @@ -329,7 +327,7 @@ class PageIndicator extends StatefulWidget { final double activeSize; - PageIndicator({ + const PageIndicator({ Key? key, this.size = 20.0, this.space = 5.0, diff --git a/lib/src/swiper.dart b/lib/src/swiper.dart index ff16502..3890e72 100644 --- a/lib/src/swiper.dart +++ b/lib/src/swiper.dart @@ -1,18 +1,22 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; -import 'package:card_swiper/card_swiper.dart'; -import 'package:card_swiper/src/flutter_page_indicator/flutter_page_indicator.dart'; -import 'package:card_swiper/src/transformer_page_view/index_controller.dart'; +// ignore_for_file: constant_identifier_names + import 'dart:async'; +import 'dart:developer'; + +import 'package:flutter/material.dart'; -import 'package:card_swiper/src/transformer_page_view/transformer_page_view.dart'; +import '../card_swiper.dart'; +import 'transformer_page_view/transformer_page_view.dart'; part 'custom_layout.dart'; -typedef SwiperOnTap = Function(int index); +typedef SwiperOnTap = void Function(int index); -typedef SwiperDataBuilder = Function( - BuildContext context, dynamic data, int index); +typedef SwiperDataBuilder = Widget Function( + BuildContext context, + T data, + int index, +); /// default auto play delay const int kDefaultAutoplayDelayMs = 3000; @@ -23,7 +27,12 @@ const int kDefaultAutoplayTransactionDuration = 300; const int kMaxValue = 2000000000; const int kMiddleValue = 1000000000; -enum SwiperLayout { DEFAULT, STACK, TINDER, CUSTOM } +enum SwiperLayout { + DEFAULT, + STACK, + TINDER, + CUSTOM, +} class Swiper extends StatefulWidget { /// If set true , the pagination will display 'outer' of the 'content' container. @@ -113,7 +122,7 @@ class Swiper extends StatefulWidget { final PageIndicatorLayout indicatorLayout; - Swiper({ + const Swiper({ this.itemBuilder, this.indicatorLayout = PageIndicatorLayout.NONE, @@ -168,7 +177,6 @@ class Swiper extends StatefulWidget { bool autoplay = false, PageTransformer? transformer, int autoplayDelay = kDefaultAutoplayDelayMs, - bool reverse = false, bool autoplayDisableOnInteraction = true, int duration = kDefaultAutoplayTransactionDuration, ValueChanged? onIndexChanged, @@ -191,10 +199,14 @@ class Swiper extends StatefulWidget { double? itemWidth, bool outer = false, double scale = 1.0, - }) { - // assert(children != null, "children must not be null"); - - return Swiper( + double? fade, + PageIndicatorLayout indicatorLayout = PageIndicatorLayout.NONE, + SwiperLayout layout = SwiperLayout.DEFAULT, + }) => + Swiper( + fade: fade, + indicatorLayout: indicatorLayout, + layout: layout, transformer: transformer, customLayoutOption: customLayoutOption, containerHeight: containerHeight, @@ -220,17 +232,17 @@ class Swiper extends StatefulWidget { plugins: plugins, physics: physics, key: key, - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return children[index]; }, - itemCount: children.length); - } + itemCount: children.length, + ); - factory Swiper.list({ + static Swiper list({ PageTransformer? transformer, - List? list, + required List list, CustomLayoutOption? customLayoutOption, - SwiperDataBuilder? builder, + required SwiperDataBuilder builder, bool autoplay = false, int autoplayDelay = kDefaultAutoplayDelayMs, bool reverse = false, @@ -255,8 +267,14 @@ class Swiper extends StatefulWidget { double? itemWidth, bool outer = false, double scale = 1.0, - }) { - return Swiper( + double? fade, + PageIndicatorLayout indicatorLayout = PageIndicatorLayout.NONE, + SwiperLayout layout = SwiperLayout.DEFAULT, + }) => + Swiper( + fade: fade, + indicatorLayout: indicatorLayout, + layout: layout, transformer: transformer, customLayoutOption: customLayoutOption, containerHeight: containerHeight, @@ -282,107 +300,94 @@ class Swiper extends StatefulWidget { loop: loop, plugins: plugins, physics: physics, - itemBuilder: (BuildContext context, int index) { - return builder!(context, list![index], index); + itemBuilder: (context, index) { + return builder(context, list[index], index); }, - itemCount: list!.length); - } + itemCount: list.length, + ); @override - State createState() { - return _SwiperState(); - } + State createState() => _SwiperState(); } abstract class _SwiperTimerMixin extends State { Timer? _timer; - - SwiperController? _controller; + late SwiperController _controller; @override void initState() { - _controller = widget.controller ?? SwiperController(); - - _controller!.addListener(_onController); - _handleAutoplay(); super.initState(); + _controller = widget.controller ?? SwiperController(); + _controller.addListener(_onController); + if (widget.autoplay) { + _controller.startAutoplay(); + } else { + _controller.stopAutoplay(); + } } void _onController() { - switch (_controller!.event) { - case SwiperController.START_AUTOPLAY: - { - if (_timer == null) { - _startAutoplay(); - } + final event = _controller.event; + if (event is AutoPlaySwiperControllerEvent) { + if (event.autoplay) { + if (_timer == null) { + _startAutoplay(); } - break; - case SwiperController.STOP_AUTOPLAY: - { - if (_timer != null) { - _stopAutoplay(); - } - } - break; + } else { + _stopAutoplay(); + } } } @override void didUpdateWidget(Swiper oldWidget) { + super.didUpdateWidget(oldWidget); if (_controller != oldWidget.controller) { - if (oldWidget.controller != null) { - oldWidget.controller!.removeListener(_onController); - _controller = oldWidget.controller; - _controller!.addListener(_onController); + final oldController = oldWidget.controller; + if (oldController != null) { + oldController.removeListener(_onController); + _controller = oldController; + _controller.addListener(_onController); + } + } + if (widget.autoplay != oldWidget.autoplay) { + if (widget.autoplay) { + _controller.startAutoplay(); + } else { + _controller.stopAutoplay(); } } - _handleAutoplay(); - super.didUpdateWidget(oldWidget); } @override void dispose() { - if (_controller != null) { - _controller!.removeListener(_onController); - // _controller.dispose(); - } - + _controller.removeListener(_onController); _stopAutoplay(); super.dispose(); } - bool _autoplayEnabled() { - return _controller!.autoplay ?? widget.autoplay; - } - - void _handleAutoplay() { - if (_autoplayEnabled() && _timer != null) return; - _stopAutoplay(); - if (_autoplayEnabled()) { - _startAutoplay(); - } - } - void _startAutoplay() { - assert(_timer == null, 'Timer must be stopped before start!'); - _timer = - Timer.periodic(Duration(milliseconds: widget.autoplayDelay), _onTimer); + _stopAutoplay(); + _timer = Timer.periodic( + Duration( + milliseconds: widget.autoplayDelay, + ), + _onTimer, + ); } void _onTimer(Timer timer) { - _controller!.next(animation: true); + _controller.next(animation: true); } void _stopAutoplay() { - if (_timer != null) { - _timer!.cancel(); - _timer = null; - } + _timer?.cancel(); + _timer = null; } } class _SwiperState extends _SwiperTimerMixin { - int? _activeIndex; + late int _activeIndex; TransformerPageController? _pageController; @@ -396,17 +401,17 @@ class _SwiperState extends _SwiperTimerMixin { @override void initState() { + super.initState(); _activeIndex = widget.index ?? widget.controller?.index ?? 0; if (_isPageViewLayout()) { _pageController = TransformerPageController( - initialPage: widget.index ?? widget.controller?.index ?? 0, - loop: widget.loop, - itemCount: widget.itemCount, - reverse: - widget.transformer == null ? false : widget.transformer!.reverse, - viewportFraction: widget.viewportFraction); + initialPage: widget.index ?? widget.controller?.index ?? 0, + loop: widget.loop, + itemCount: widget.itemCount, + reverse: widget.transformer?.reverse ?? false, + viewportFraction: widget.viewportFraction, + ); } - super.initState(); } bool _isPageViewLayout() { @@ -418,8 +423,7 @@ class _SwiperState extends _SwiperTimerMixin { super.didChangeDependencies(); } - bool _getReverse(Swiper widget) => - widget.transformer == null ? false : widget.transformer!.reverse; + bool _getReverse(Swiper widget) => widget.transformer?.reverse ?? false; @override void didUpdateWidget(Swiper oldWidget) { @@ -432,11 +436,12 @@ class _SwiperState extends _SwiperTimerMixin { widget.viewportFraction != oldWidget.viewportFraction || _getReverse(widget) != _getReverse(oldWidget))) { _pageController = TransformerPageController( - initialPage: widget.index ?? widget.controller?.index ?? 0, - loop: widget.loop, - itemCount: widget.itemCount, - reverse: _getReverse(widget), - viewportFraction: widget.viewportFraction); + initialPage: widget.index ?? widget.controller?.index ?? 0, + loop: widget.loop, + itemCount: widget.itemCount, + reverse: _getReverse(widget), + viewportFraction: widget.viewportFraction, + ); } } else { scheduleMicrotask(() { @@ -448,17 +453,15 @@ class _SwiperState extends _SwiperTimerMixin { }); } if (widget.index != null && widget.index != _activeIndex) { - _activeIndex = widget.index; + _activeIndex = widget.index!; } } - void _onIndexChanged(int? index) { + void _onIndexChanged(int index) { setState(() { _activeIndex = index; }); - if (widget.onIndexChanged != null) { - widget.onIndexChanged!(index!); - } + widget.onIndexChanged?.call(index); } Widget _buildSwiper() { @@ -484,13 +487,14 @@ class _SwiperState extends _SwiperTimerMixin { scrollDirection: widget.scrollDirection, ); } else if (_isPageViewLayout()) { + //default var transformer = widget.transformer; if (widget.scale != null || widget.fade != null) { transformer = ScaleAndFadeTransformer(scale: widget.scale, fade: widget.fade); } - Widget child = TransformerPageView( + final child = TransformerPageView( pageController: _pageController, loop: widget.loop, itemCount: widget.itemCount, @@ -507,7 +511,7 @@ class _SwiperState extends _SwiperTimerMixin { ); if (widget.autoplayDisableOnInteraction && widget.autoplay) { return NotificationListener( - onNotification: (ScrollNotification notification) { + onNotification: (notification) { if (notification is ScrollStartNotification) { if (notification.dragDetails != null) { //by human @@ -554,64 +558,79 @@ class _SwiperState extends _SwiperTimerMixin { scrollDirection: widget.scrollDirection, ); } else { - return SizedBox.shrink(); + return const SizedBox.shrink(); } } SwiperPluginConfig _ensureConfig(SwiperPluginConfig? config) { - config ??= SwiperPluginConfig( - outer: widget.outer, - itemCount: widget.itemCount, - layout: widget.layout, - indicatorLayout: widget.indicatorLayout, - pageController: _pageController, - activeIndex: _activeIndex, - scrollDirection: widget.scrollDirection, - controller: _controller!, - loop: widget.loop); + final con = config ?? + SwiperPluginConfig( + outer: widget.outer, + itemCount: widget.itemCount, + layout: widget.layout, + indicatorLayout: widget.indicatorLayout, + pageController: _pageController, + activeIndex: _activeIndex, + scrollDirection: widget.scrollDirection, + controller: _controller, + loop: widget.loop, + ); - return config; + return con; } - List? _ensureListForStack( - Widget swiper, List? listForStack, Widget widget) { + List? _ensureListForStack({ + required Widget swiper, + required List? listForStack, + required Widget widget, + }) { + final resList = []; if (listForStack == null) { - listForStack = [swiper, widget]; + resList.addAll([swiper, widget]); } else { - listForStack.add(widget); + resList.addAll([...listForStack, widget]); } - return listForStack; + return resList; } @override Widget build(BuildContext context) { - var swiper = _buildSwiper(); + final swiper = _buildSwiper(); List? listForStack; SwiperPluginConfig? config; if (widget.control != null) { //Stack config = _ensureConfig(config); listForStack = _ensureListForStack( - swiper, listForStack, widget.control!.build(context, config)); + swiper: swiper, + listForStack: listForStack, + widget: widget.control!.build(context, config), + ); } if (widget.plugins != null) { config = _ensureConfig(config); for (final plugin in widget.plugins!) { listForStack = _ensureListForStack( - swiper, listForStack, plugin.build(context, config)); + swiper: swiper, + listForStack: listForStack, + widget: plugin.build(context, config), + ); } } if (widget.pagination != null) { config = _ensureConfig(config); if (widget.outer) { return _buildOuterPagination( - widget.pagination as SwiperPagination, + widget.pagination! as SwiperPagination, listForStack == null ? swiper : Stack(children: listForStack), config); } else { listForStack = _ensureListForStack( - swiper, listForStack, widget.pagination!.build(context, config)); + swiper: swiper, + listForStack: listForStack, + widget: widget.pagination!.build(context, config), + ); } } @@ -625,8 +644,11 @@ class _SwiperState extends _SwiperTimerMixin { } Widget _buildOuterPagination( - SwiperPagination pagination, Widget swiper, SwiperPluginConfig config) { - var list = []; + SwiperPagination pagination, + Widget swiper, + SwiperPluginConfig config, + ) { + final list = []; //Only support bottom yet! if (widget.containerHeight != null || widget.containerWidth != null) { list.add(swiper); @@ -649,58 +671,58 @@ class _SwiperState extends _SwiperTimerMixin { abstract class _SubSwiper extends StatefulWidget { final IndexedWidgetBuilder? itemBuilder; - final int? itemCount; + final int itemCount; final int? index; final ValueChanged? onIndexChanged; - final SwiperController? controller; + final SwiperController controller; final int? duration; - final Curve? curve; + final Curve curve; final double? itemWidth; final double? itemHeight; - final bool? loop; + final bool loop; final Axis? scrollDirection; - _SubSwiper( - {Key? key, - this.loop, - this.itemHeight, - this.itemWidth, - this.duration, - this.curve, - this.itemBuilder, - this.controller, - this.index, - this.itemCount, - this.scrollDirection = Axis.horizontal, - this.onIndexChanged}) - : super(key: key); + const _SubSwiper({ + Key? key, + required this.loop, + this.itemHeight, + this.itemWidth, + this.duration, + required this.curve, + this.itemBuilder, + required this.controller, + this.index, + required this.itemCount, + this.scrollDirection = Axis.horizontal, + this.onIndexChanged, + }) : super(key: key); @override State createState(); int getCorrectIndex(int indexNeedsFix) { if (itemCount == 0) return 0; - var value = indexNeedsFix % itemCount!; + var value = indexNeedsFix % itemCount; if (value < 0) { - value += itemCount!; + value += itemCount; } return value; } } class _TinderSwiper extends _SubSwiper { - _TinderSwiper({ + const _TinderSwiper({ Key? key, - Curve? curve, + required Curve curve, int? duration, - SwiperController? controller, + required SwiperController controller, ValueChanged? onIndexChanged, double? itemHeight, double? itemWidth, IndexedWidgetBuilder? itemBuilder, int? index, - bool? loop, - int? itemCount, + required bool loop, + required int itemCount, Axis? scrollDirection, }) : assert(itemWidth != null && itemHeight != null), super( @@ -724,43 +746,42 @@ class _TinderSwiper extends _SubSwiper { } class _StackSwiper extends _SubSwiper { - _StackSwiper({ + const _StackSwiper({ Key? key, - Curve? curve, + required Curve curve, int? duration, - SwiperController? controller, + required SwiperController controller, ValueChanged? onIndexChanged, double? itemHeight, double? itemWidth, IndexedWidgetBuilder? itemBuilder, int? index, - bool? loop, - int? itemCount, + required bool loop, + required int itemCount, Axis? scrollDirection, }) : super( - loop: loop, - key: key, - itemWidth: itemWidth, - itemHeight: itemHeight, - itemBuilder: itemBuilder, - curve: curve, - duration: duration, - controller: controller, - index: index, - onIndexChanged: onIndexChanged, - itemCount: itemCount, - scrollDirection: scrollDirection); + loop: loop, + key: key, + itemWidth: itemWidth, + itemHeight: itemHeight, + itemBuilder: itemBuilder, + curve: curve, + duration: duration, + controller: controller, + index: index, + onIndexChanged: onIndexChanged, + itemCount: itemCount, + scrollDirection: scrollDirection, + ); @override - State createState() { - return _StackViewState(); - } + State createState() => _StackViewState(); } class _TinderState extends _CustomLayoutStateBase<_TinderSwiper> { late List scales; - late List offsetsX; - late List offsetsY; + late List offsetsX; + late List offsetsY; late List opacity; late List rotates; @@ -818,11 +839,11 @@ class _TinderState extends _CustomLayoutStateBase<_TinderSwiper> { @override Widget _buildItem(int i, int realIndex, double animationValue) { - final s = _getValue(scales, animationValue, i)!; - final f = _getValue(offsetsX, animationValue, i)!; - final fy = _getValue(offsetsY, animationValue, i)!; - final o = _getValue(opacity, animationValue, i)!; - final a = _getValue(rotates, animationValue, i)!; + final s = _getValue(scales, animationValue, i); + final f = _getValue(offsetsX, animationValue, i); + final fy = _getValue(offsetsY, animationValue, i); + final o = _getValue(opacity, animationValue, i); + final a = _getValue(rotates, animationValue, i); final alignment = widget.scrollDirection == Axis.horizontal ? Alignment.bottomCenter @@ -852,7 +873,7 @@ class _TinderState extends _CustomLayoutStateBase<_TinderSwiper> { class _StackViewState extends _CustomLayoutStateBase<_StackSwiper> { late List scales; - late List offsets; + late List offsets; late List opacity; @override @@ -862,10 +883,10 @@ class _StackViewState extends _CustomLayoutStateBase<_StackSwiper> { void _updateValues() { if (widget.scrollDirection == Axis.horizontal) { - final space = (_swiperWidth! - widget.itemWidth!) / 2; + final space = (_swiperWidth - widget.itemWidth!) / 2; offsets = [-space, -space / 3 * 2, -space / 3, 0.0, _swiperWidth]; } else { - final space = (_swiperHeight! - widget.itemHeight!) / 2; + final space = (_swiperHeight - widget.itemHeight!) / 2; offsets = [-space, -space / 3 * 2, -space / 3, 0.0, _swiperHeight]; } } @@ -893,13 +914,13 @@ class _StackViewState extends _CustomLayoutStateBase<_StackSwiper> { @override Widget _buildItem(int i, int realIndex, double animationValue) { - final s = _getValue(scales, animationValue, i)!; + final s = _getValue(scales, animationValue, i); final f = _getValue(offsets, animationValue, i); - final o = _getValue(opacity, animationValue, i)!; + final o = _getValue(opacity, animationValue, i); final offset = widget.scrollDirection == Axis.horizontal - ? Offset(f!, 0.0) - : Offset(0.0, f!); + ? Offset(f, 0.0) + : Offset(0.0, f); final alignment = widget.scrollDirection == Axis.horizontal ? Alignment.centerLeft @@ -933,28 +954,28 @@ class ScaleAndFadeTransformer extends PageTransformer { _scale = scale; @override - Widget transform(Widget item, TransformInfo info) { + Widget transform(Widget child, TransformInfo info) { final position = info.position; - var child = item; + var c = child; if (_scale != null) { final scaleFactor = (1 - position!.abs()) * (1 - _scale!); final scale = _scale! + scaleFactor; - child = Transform.scale( + c = Transform.scale( scale: scale, - child: item, + child: c, ); } if (_fade != null) { final fadeFactor = (1 - position!.abs()) * (1 - _fade!); final opacity = _fade! + fadeFactor; - child = Opacity( + c = Opacity( opacity: opacity, - child: child, + child: c, ); } - return child; + return c; } } diff --git a/lib/src/swiper_control.dart b/lib/src/swiper_control.dart index 973033e..f0df0a5 100644 --- a/lib/src/swiper_control.dart +++ b/lib/src/swiper_control.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; import 'package:card_swiper/card_swiper.dart'; +import 'package:flutter/material.dart'; class SwiperControl extends SwiperPlugin { ///IconData for previous @@ -32,8 +32,13 @@ class SwiperControl extends SwiperPlugin { this.padding = const EdgeInsets.all(5.0), }); - Widget buildButton(SwiperPluginConfig? config, Color color, IconData iconDaga, - int quarterTurns, bool previous) { + Widget buildButton({ + required SwiperPluginConfig? config, + required Color color, + required IconData iconDaga, + required int quarterTurns, + required bool previous, + }) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { @@ -57,19 +62,19 @@ class SwiperControl extends SwiperPlugin { } @override - Widget build(BuildContext context, SwiperPluginConfig? config) { + Widget build(BuildContext context, SwiperPluginConfig config) { final themeData = Theme.of(context); final color = this.color ?? themeData.primaryColor; final disableColor = this.disableColor ?? themeData.disabledColor; - var prevColor; - var nextColor; + Color prevColor; + Color nextColor; - if (config!.loop!) { + if (config.loop) { prevColor = nextColor = color; } else { - final next = config.activeIndex! < config.itemCount! - 1; - final prev = config.activeIndex! > 0; + final next = config.activeIndex < config.itemCount - 1; + final prev = config.activeIndex > 0; prevColor = prev ? color : disableColor; nextColor = next ? color : disableColor; } @@ -80,8 +85,20 @@ class SwiperControl extends SwiperPlugin { key: key, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - buildButton(config, prevColor, iconPrevious, 0, true), - buildButton(config, nextColor, iconNext, 0, false) + buildButton( + config: config, + color: prevColor, + iconDaga: iconPrevious, + quarterTurns: 0, + previous: true, + ), + buildButton( + config: config, + color: nextColor, + iconDaga: iconNext, + quarterTurns: 0, + previous: false, + ) ], ); } else { @@ -89,13 +106,25 @@ class SwiperControl extends SwiperPlugin { key: key, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - buildButton(config, prevColor, iconPrevious, -3, true), - buildButton(config, nextColor, iconNext, -3, false) + buildButton( + config: config, + color: prevColor, + iconDaga: iconPrevious, + quarterTurns: -3, + previous: true, + ), + buildButton( + config: config, + color: nextColor, + iconDaga: iconNext, + quarterTurns: -3, + previous: false, + ) ], ); } - return Container( + return SizedBox( height: double.infinity, width: double.infinity, child: child, diff --git a/lib/src/swiper_controller.dart b/lib/src/swiper_controller.dart index 335c46c..423c1fb 100644 --- a/lib/src/swiper_controller.dart +++ b/lib/src/swiper_controller.dart @@ -1,46 +1,45 @@ -import 'package:card_swiper/src/swiper_plugin.dart'; -import 'package:card_swiper/src/transformer_page_view/index_controller.dart'; - -class SwiperController extends IndexController { - // Autoplay is started - static const int START_AUTOPLAY = 2; - - // Autoplay is stopped. - static const int STOP_AUTOPLAY = 3; - - // Indicate that the user is swiping - static const int SWIPE = 4; - - // Indicate that the `Swiper` has changed it's index and is building it's ui ,so that the - // `SwiperPluginConfig` is available. - static const int BUILD = 5; - - // available when `event` == SwiperController.BUILD - SwiperPluginConfig? config; - - // available when `event` == SwiperController.SWIPE - // this value is PageViewController.pos - double? pos; - - @override - int? index; - - @override - bool? animation; +import 'swiper_plugin.dart'; +import 'transformer_page_view/index_controller.dart'; + +class SwipeIndexControllerEvent extends IndexControllerEventBase { + SwipeIndexControllerEvent({ + required this.pos, + required bool animation, + }) : super(animation: animation); + final double pos; +} - bool? autoplay; +class BuildIndexControllerEvent extends IndexControllerEventBase { + BuildIndexControllerEvent({ + required bool animation, + required this.config, + }) : super(animation: animation); + final SwiperPluginConfig config; +} - SwiperController(); +class AutoPlaySwiperControllerEvent extends IndexControllerEventBase { + AutoPlaySwiperControllerEvent({ + required bool animation, + required this.autoplay, + }) : super(animation: animation); + + AutoPlaySwiperControllerEvent.start({ + required bool animation, + }) : this(animation: animation, autoplay: true); + AutoPlaySwiperControllerEvent.stop({ + required bool animation, + }) : this(animation: animation, autoplay: false); + final bool autoplay; +} - void startAutoplay() { - event = SwiperController.START_AUTOPLAY; - autoplay = true; +class SwiperController extends IndexController { + void startAutoplay({bool animation = true}) { + event = AutoPlaySwiperControllerEvent.start(animation: animation); notifyListeners(); } - void stopAutoplay() { - event = SwiperController.STOP_AUTOPLAY; - autoplay = false; + void stopAutoplay({bool animation = true}) { + event = AutoPlaySwiperControllerEvent.stop(animation: animation); notifyListeners(); } } diff --git a/lib/src/swiper_pagination.dart b/lib/src/swiper_pagination.dart index eda3f47..88365b8 100644 --- a/lib/src/swiper_pagination.dart +++ b/lib/src/swiper_pagination.dart @@ -1,7 +1,8 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; -import 'package:card_swiper/card_swiper.dart'; -import 'package:card_swiper/src/flutter_page_indicator/flutter_page_indicator.dart'; + +import '../card_swiper.dart'; class FractionPaginationBuilder extends SwiperPlugin { ///color ,if set null , will be Theme.of(context).scaffoldBackgroundColor @@ -38,7 +39,7 @@ class FractionPaginationBuilder extends SwiperPlugin { mainAxisSize: MainAxisSize.min, children: [ Text( - '${config.activeIndex! + 1}', + '${config.activeIndex + 1}', style: TextStyle(color: activeColor, fontSize: activeFontSize), ), Text( @@ -57,7 +58,7 @@ class FractionPaginationBuilder extends SwiperPlugin { mainAxisSize: MainAxisSize.min, children: [ Text( - '${config.activeIndex! + 1}', + '${config.activeIndex + 1}', style: TextStyle(color: activeColor, fontSize: activeFontSize), ), Text( @@ -98,26 +99,25 @@ class RectSwiperPaginationBuilder extends SwiperPlugin { }); @override - Widget build(BuildContext context, SwiperPluginConfig? config) { + Widget build(BuildContext context, SwiperPluginConfig config) { final themeData = Theme.of(context); final activeColor = this.activeColor ?? themeData.primaryColor; final color = this.color ?? themeData.scaffoldBackgroundColor; - var list = []; + final list = []; - if (config!.itemCount! > 20) { - print( + final itemCount = config.itemCount; + final activeIndex = config.activeIndex; + if (itemCount > 20) { + log( 'The itemCount is too big, we suggest use FractionPaginationBuilder ' 'instead of DotSwiperPaginationBuilder in this situation', ); } - var itemCount = config.itemCount!; - var activeIndex = config.activeIndex; - for (var i = 0; i < itemCount; ++i) { - var active = i == activeIndex; - var size = active ? activeSize : this.size; + final active = i == activeIndex; + final size = active ? activeSize : this.size; list.add(SizedBox( width: size.width, height: size.height, @@ -173,9 +173,9 @@ class DotSwiperPaginationBuilder extends SwiperPlugin { }); @override - Widget build(BuildContext context, SwiperPluginConfig? config) { - if (config!.itemCount! > 20) { - print( + Widget build(BuildContext context, SwiperPluginConfig config) { + if (config.itemCount > 20) { + log( 'The itemCount is too big, we suggest use FractionPaginationBuilder ' 'instead of DotSwiperPaginationBuilder in this situation', ); @@ -192,7 +192,7 @@ class DotSwiperPaginationBuilder extends SwiperPlugin { if (config.indicatorLayout != PageIndicatorLayout.NONE && config.layout == SwiperLayout.DEFAULT) { return PageIndicator( - count: config.itemCount!, + count: config.itemCount, controller: config.pageController!, layout: config.indicatorLayout, size: size, @@ -202,13 +202,13 @@ class DotSwiperPaginationBuilder extends SwiperPlugin { ); } - var list = []; + final list = []; - var itemCount = config.itemCount!; - var activeIndex = config.activeIndex; + final itemCount = config.itemCount; + final activeIndex = config.activeIndex; for (var i = 0; i < itemCount; ++i) { - var active = i == activeIndex; + final active = i == activeIndex; list.add(Container( key: Key('pagination_$i'), margin: EdgeInsets.all(space), @@ -238,9 +238,9 @@ class DotSwiperPaginationBuilder extends SwiperPlugin { } } -typedef SwiperPaginationBuilder = Function( +typedef SwiperPaginationBuilder = Widget Function( BuildContext context, - SwiperPluginConfig? config, + SwiperPluginConfig config, ); class SwiperCustomPagination extends SwiperPlugin { @@ -249,7 +249,7 @@ class SwiperCustomPagination extends SwiperPlugin { const SwiperCustomPagination({required this.builder}); @override - Widget build(BuildContext context, SwiperPluginConfig? config) { + Widget build(BuildContext context, SwiperPluginConfig config) { return builder(context, config); } } @@ -283,8 +283,8 @@ class SwiperPagination extends SwiperPlugin { }); @override - Widget build(BuildContext context, SwiperPluginConfig? config) { - final alignment = config!.scrollDirection == Axis.horizontal + Widget build(BuildContext context, SwiperPluginConfig config) { + final alignment = config.scrollDirection == Axis.horizontal ? Alignment.bottomCenter : Alignment.centerRight; Widget child = Container( diff --git a/lib/src/swiper_plugin.dart b/lib/src/swiper_plugin.dart index 683a40f..db49f67 100644 --- a/lib/src/swiper_plugin.dart +++ b/lib/src/swiper_plugin.dart @@ -1,6 +1,5 @@ import 'package:flutter/widgets.dart'; -import 'package:card_swiper/card_swiper.dart'; -import 'package:card_swiper/src/flutter_page_indicator/flutter_page_indicator.dart'; +import '../card_swiper.dart'; /// plugin to display swiper components /// @@ -13,10 +12,10 @@ abstract class SwiperPlugin { class SwiperPluginConfig { final Axis scrollDirection; final SwiperController controller; - final int? activeIndex; - final int? itemCount; + final int activeIndex; + final int itemCount; final PageIndicatorLayout? indicatorLayout; - final bool? loop; + final bool loop; final bool? outer; final PageController? pageController; final SwiperLayout? layout; @@ -24,13 +23,13 @@ class SwiperPluginConfig { const SwiperPluginConfig({ required this.scrollDirection, required this.controller, - this.activeIndex, - this.itemCount, + required this.activeIndex, + required this.itemCount, this.indicatorLayout, this.outer, this.pageController, this.layout, - this.loop, + this.loop = false, }); } @@ -38,7 +37,11 @@ class SwiperPluginView extends StatelessWidget { final SwiperPlugin plugin; final SwiperPluginConfig config; - const SwiperPluginView(this.plugin, this.config); + const SwiperPluginView({ + Key? key, + required this.plugin, + required this.config, + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/src/transformer_page_view/index_controller.dart b/lib/src/transformer_page_view/index_controller.dart index 654898b..f8ea30a 100644 --- a/lib/src/transformer_page_view/index_controller.dart +++ b/lib/src/transformer_page_view/index_controller.dart @@ -3,45 +3,117 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; -class IndexController extends ChangeNotifier { - static const int NEXT = 1; - static const int PREVIOUS = -1; - static const int MOVE = 0; +abstract class IndexControllerEventBase { + final bool animation; + + final completer = Completer(); + Future get future => completer.future; + void complete() { + if (!completer.isCompleted) { + completer.complete(); + } + } + + IndexControllerEventBase({ + required this.animation, + }); +} + +mixin TargetedPositionControllerEvent on IndexControllerEventBase { + double get targetPosition; +} +mixin StepBasedIndexControllerEvent on TargetedPositionControllerEvent { + int get step; + int calcNextIndex({ + required int currentIndex, + required int itemCount, + required bool loop, + required bool reverse, + }) { + var cIndex = currentIndex; + if (reverse) { + cIndex -= step; + } else { + cIndex += step; + } + + if (!loop) { + if (cIndex >= itemCount) { + cIndex = 0; + } else if (cIndex < 0) { + cIndex = itemCount - 1; + } + } + return cIndex; + } +} + +class NextIndexControllerEvent extends IndexControllerEventBase + with TargetedPositionControllerEvent, StepBasedIndexControllerEvent { + NextIndexControllerEvent({ + required bool animation, + }) : super( + animation: animation, + ); - late Completer _completer; + @override + int get step => 1; + + @override + double get targetPosition => 1; +} - int? index; - bool? animation; - int? event; +class PrevIndexControllerEvent extends IndexControllerEventBase + with TargetedPositionControllerEvent, StepBasedIndexControllerEvent { + PrevIndexControllerEvent({ + required bool animation, + }) : super( + animation: animation, + ); + @override + int get step => -1; + @override + double get targetPosition => 0; +} + +class MoveIndexControllerEvent extends IndexControllerEventBase + with TargetedPositionControllerEvent { + final int newIndex; + final int oldIndex; + MoveIndexControllerEvent({ + required this.newIndex, + required this.oldIndex, + required bool animation, + }) : super( + animation: animation, + ); + @override + double get targetPosition => newIndex > oldIndex ? 1 : 0; +} + +class IndexController extends ChangeNotifier { + IndexControllerEventBase? event; + int index = 0; Future move(int index, {bool animation = true}) { - this.animation = animation; - this.index = index; - event = MOVE; - _completer = Completer(); + final e = event = MoveIndexControllerEvent( + animation: animation, + newIndex: index, + oldIndex: this.index, + ); notifyListeners(); - return _completer.future; + return e.future; } Future next({bool animation = true}) { - event = NEXT; - this.animation = animation; - _completer = Completer(); + final e = event = NextIndexControllerEvent(animation: animation); notifyListeners(); - return _completer.future; + return e.future; } Future previous({bool animation = true}) { - event = PREVIOUS; - this.animation = animation; - _completer = Completer(); + final e = event = PrevIndexControllerEvent(animation: animation); notifyListeners(); - return _completer.future; - } - - void complete() { - if (!_completer.isCompleted) { - _completer.complete(); - } + return e.future; } } diff --git a/lib/src/transformer_page_view/parallax.dart b/lib/src/transformer_page_view/parallax.dart index fd8b81c..439b0d7 100644 --- a/lib/src/transformer_page_view/parallax.dart +++ b/lib/src/transformer_page_view/parallax.dart @@ -1,5 +1,5 @@ import 'package:flutter/widgets.dart'; -import 'package:card_swiper/src/transformer_page_view/transformer_page_view.dart'; +import 'transformer_page_view.dart'; typedef PaintCallback = Function(Canvas canvas, Size size); @@ -12,7 +12,7 @@ class ColorPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - var index = info.fromIndex!; + final index = info.fromIndex; _paint.color = colors[index]; canvas.drawRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height), _paint); if (info.done!) { @@ -86,11 +86,12 @@ class ParallaxColor extends StatefulWidget { final TransformInfo info; - ParallaxColor({ + const ParallaxColor({ + Key? key, + required this.child, required this.colors, required this.info, - required this.child, - }); + }) : super(key: key); @override State createState() { @@ -105,11 +106,12 @@ class ParallaxContainer extends StatelessWidget { final double opacityFactor; const ParallaxContainer({ + Key? key, required this.child, required this.position, this.translationFactor = 100.0, this.opacityFactor = 1.0, - }); + }) : super(key: key); @override Widget build(BuildContext context) { @@ -127,14 +129,20 @@ class ParallaxImage extends StatelessWidget { final Image image; final double imageFactor; - ParallaxImage.asset(String name, - {required double position, this.imageFactor = 0.3}) - : image = Image.asset(name, - fit: BoxFit.cover, - alignment: FractionalOffset( - 0.5 + position * imageFactor, - 0.5, - )); + ParallaxImage.asset( + String name, { + Key? key, + required double position, + this.imageFactor = 0.3, + }) : image = Image.asset( + name, + fit: BoxFit.cover, + alignment: FractionalOffset( + 0.5 + position * imageFactor, + 0.5, + ), + ), + super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/src/transformer_page_view/transformer_page_view.dart b/lib/src/transformer_page_view/transformer_page_view.dart index d4a1de8..a0dffd6 100644 --- a/lib/src/transformer_page_view/transformer_page_view.dart +++ b/lib/src/transformer_page_view/transformer_page_view.dart @@ -1,7 +1,7 @@ library transformer_page_view; import 'package:flutter/widgets.dart'; -import 'package:card_swiper/src/transformer_page_view/index_controller.dart'; +import 'index_controller.dart'; /// /// NOTICE:: @@ -42,7 +42,7 @@ class TransformInfo { /// The `activeIndex` of the PageView, from user start to swipe /// It will change when user end drag - final int? fromIndex; + final int fromIndex; /// Next `index` is greater than this `index` final bool? forward; @@ -62,7 +62,7 @@ class TransformInfo { this.width, this.height, this.activeIndex, - this.fromIndex, + required this.fromIndex, this.forward, this.done, this.viewportFraction, @@ -80,8 +80,10 @@ abstract class PageTransformer { Widget transform(Widget child, TransformInfo info); } -typedef PageTransformerBuilderCallback = Function( - Widget child, TransformInfo info); +typedef PageTransformerBuilderCallback = Widget Function( + Widget child, + TransformInfo info, +); class PageTransformerBuilder extends PageTransformer { final PageTransformerBuilderCallback builder; @@ -113,7 +115,7 @@ class TransformerPageController extends PageController { keepPage: keepPage, viewportFraction: viewportFraction); - int? getRenderIndexFromRealIndex(num index) { + int getRenderIndexFromRealIndex(num index) { return _getRenderIndexFromRealIndex(index, loop, itemCount, reverse); } @@ -122,21 +124,25 @@ class TransformerPageController extends PageController { return loop ? itemCount + kMaxValue : itemCount; } - static int? _getRenderIndexFromRealIndex( - num? index, bool loop, int? itemCount, bool reverse) { + static int _getRenderIndexFromRealIndex( + num index, + bool loop, + int itemCount, + bool reverse, + ) { if (itemCount == 0) return 0; - int? renderIndex; + int renderIndex; if (loop) { - renderIndex = index! - kMiddleValue as int?; - renderIndex = renderIndex! % itemCount!; + renderIndex = (index - kMiddleValue).toInt(); + renderIndex = renderIndex % itemCount; if (renderIndex < 0) { renderIndex += itemCount; } } else { - renderIndex = index as int?; + renderIndex = index.toInt(); } if (reverse) { - renderIndex = itemCount! - renderIndex! - 1; + renderIndex = itemCount - renderIndex - 1; } return renderIndex; @@ -145,11 +151,15 @@ class TransformerPageController extends PageController { double get realPage => super.page ?? 0.0; static double? _getRenderPageFromRealPage( - double? page, bool loop, int? itemCount, bool reverse) { + double page, + bool loop, + int itemCount, + bool reverse, + ) { double? renderPage; if (loop) { - renderPage = page! - kMiddleValue; - renderPage = renderPage % itemCount!; + renderPage = page - kMiddleValue; + renderPage = renderPage % itemCount; if (renderPage < 0) { renderPage += itemCount; } @@ -157,7 +167,7 @@ class TransformerPageController extends PageController { renderPage = page; } if (reverse) { - renderPage = itemCount! - renderPage! - 1; + renderPage = itemCount - renderPage - 1; } return renderPage; @@ -170,7 +180,7 @@ class TransformerPageController extends PageController { : realPage; } - int? getRealIndexFromRenderIndex(num index) { + int getRealIndexFromRenderIndex(num index) { return _getRealIndexFromRenderIndex(index, loop, itemCount, reverse); } @@ -204,7 +214,7 @@ class TransformerPageView extends StatefulWidget { /// Called whenever the page in the center of the viewport changes. /// Same as [PageView.onPageChanged] - final ValueChanged? onPageChanged; + final ValueChanged? onPageChanged; final IndexedWidgetBuilder? itemBuilder; @@ -243,13 +253,13 @@ class TransformerPageView extends StatefulWidget { /// /// [itemBuilder] will be called only with indices greater than or equal to /// zero and less than [itemCount]. - TransformerPageView({ + const TransformerPageView({ Key? key, this.index, Duration? duration, this.curve = Curves.ease, this.viewportFraction = 1.0, - this.loop = false, + required this.loop, this.scrollDirection = Axis.horizontal, this.physics, this.pageSnapping = true, @@ -260,28 +270,29 @@ class TransformerPageView extends StatefulWidget { this.pageController, required this.itemCount, }) : assert(itemCount == 0 || itemBuilder != null || transformer != null), - duration = - duration ?? Duration(milliseconds: kDefaultTransactionDuration), + duration = duration ?? + const Duration(milliseconds: kDefaultTransactionDuration), super(key: key); - factory TransformerPageView.children( - {Key? key, - int? index, - Duration? duration, - Curve curve = Curves.ease, - double viewportFraction = 1.0, - bool loop = false, - Axis scrollDirection = Axis.horizontal, - ScrollPhysics? physics, - bool pageSnapping = true, - ValueChanged? onPageChanged, - IndexController? controller, - PageTransformer? transformer, - required List children, - TransformerPageController? pageController}) { + factory TransformerPageView.children({ + Key? key, + int? index, + Duration? duration, + Curve curve = Curves.ease, + double viewportFraction = 1.0, + bool loop = false, + Axis scrollDirection = Axis.horizontal, + ScrollPhysics? physics, + bool pageSnapping = true, + ValueChanged? onPageChanged, + IndexController? controller, + PageTransformer? transformer, + required List children, + TransformerPageController? pageController, + }) { return TransformerPageView( itemCount: children.length, - itemBuilder: (BuildContext context, int index) { + itemBuilder: (context, index) { return children[index]; }, pageController: pageController, @@ -289,6 +300,7 @@ class TransformerPageView extends StatefulWidget { pageSnapping: pageSnapping, key: key, index: index, + loop: loop, duration: duration, curve: curve, viewportFraction: viewportFraction, @@ -300,11 +312,9 @@ class TransformerPageView extends StatefulWidget { } @override - State createState() { - return _TransformerPageViewState(); - } + State createState() => _TransformerPageViewState(); - static int? getRealIndexFromRenderIndex({ + static int getRealIndexFromRenderIndex({ required bool reverse, int index = 0, int itemCount = 0, @@ -317,57 +327,58 @@ class TransformerPageView extends StatefulWidget { return initPage; } - static PageController createPageController( - {required bool reverse, - int index = 0, - int itemCount = 0, - required bool loop, - required double viewportFraction}) { + static PageController createPageController({ + required bool reverse, + int index = 0, + int itemCount = 0, + required bool loop, + required double viewportFraction, + }) { return PageController( - initialPage: getRealIndexFromRenderIndex( - reverse: reverse, index: index, itemCount: itemCount, loop: loop)!, - viewportFraction: viewportFraction); + initialPage: getRealIndexFromRenderIndex( + reverse: reverse, + index: index, + itemCount: itemCount, + loop: loop, + ), + viewportFraction: viewportFraction, + ); } } class _TransformerPageViewState extends State { Size? _size; int _activeIndex = 0; - double? _currentPixels; + late double _currentPixels; bool _done = false; ///This value will not change until user end drag. - int? _fromIndex; + late int _fromIndex; PageTransformer? _transformer; - TransformerPageController? _pageController; + late TransformerPageController _pageController; Widget _buildItemNormal(BuildContext context, int index) { - final renderIndex = _pageController!.getRenderIndexFromRealIndex(index)!; + final renderIndex = _pageController.getRenderIndexFromRealIndex(index); return widget.itemBuilder!(context, renderIndex); } Widget _buildItem(BuildContext context, int index) { return AnimatedBuilder( - animation: _pageController!, - builder: (BuildContext c, Widget? w) { - var renderIndex = _pageController!.getRenderIndexFromRealIndex(index); - Widget? child; - if (widget.itemBuilder != null) { - child = widget.itemBuilder!(context, renderIndex!); - } - - child ??= Container(); - + animation: _pageController, + builder: (c, w) { + final renderIndex = + _pageController.getRenderIndexFromRealIndex(index); + final child = widget.itemBuilder?.call(context, renderIndex) ?? + const SizedBox.shrink(); if (_size == null) { return child; } double position; - double? page = _pageController!.realPage; - + final page = _pageController.realPage; if (_transformer!.reverse) { position = page - index; } else { @@ -381,9 +392,9 @@ class _TransformerPageViewState extends State { height: _size!.height, position: position.clamp(-1.0, 1.0), activeIndex: - _pageController!.getRenderIndexFromRealIndex(_activeIndex), + _pageController.getRenderIndexFromRealIndex(_activeIndex), fromIndex: _fromIndex, - forward: _pageController!.position.pixels - _currentPixels! >= 0, + forward: _pageController.position.pixels - _currentPixels >= 0, done: _done, scrollDirection: widget.scrollDirection, viewportFraction: widget.viewportFraction, @@ -394,10 +405,9 @@ class _TransformerPageViewState extends State { } double? _calcCurrentPixels() { - _currentPixels = - _pageController!.getRenderIndexFromRealIndex(_activeIndex)! * - _pageController!.position.viewportDimension * - widget.viewportFraction; + _currentPixels = _pageController.getRenderIndexFromRealIndex(_activeIndex) * + _pageController.position.viewportDimension * + widget.viewportFraction; // print("activeIndex:$_activeIndex , pix:$_currentPixels"); @@ -407,21 +417,21 @@ class _TransformerPageViewState extends State { @override Widget build(BuildContext context) { final builder = _transformer == null ? _buildItemNormal : _buildItem; - var child = PageView.builder( + final child = PageView.builder( itemBuilder: builder, - itemCount: _pageController!.getRealItemCount(), + itemCount: _pageController.getRealItemCount(), onPageChanged: _onIndexChanged, controller: _pageController, scrollDirection: widget.scrollDirection, physics: widget.physics, pageSnapping: widget.pageSnapping, - reverse: _pageController!.reverse, + reverse: _pageController.reverse, ); if (_transformer == null) { return child; } return NotificationListener( - onNotification: (ScrollNotification notification) { + onNotification: (notification) { if (notification is ScrollStartNotification) { _calcCurrentPixels(); _done = false; @@ -440,13 +450,11 @@ class _TransformerPageViewState extends State { void _onIndexChanged(int index) { _activeIndex = index; - if (widget.onPageChanged != null) { - widget - .onPageChanged!(_pageController!.getRenderIndexFromRealIndex(index)); - } + widget.onPageChanged + ?.call(_pageController.getRenderIndexFromRealIndex(index)); } - void _onGetSize(_) { + void _onGetSize(Duration _) { Size? size; // if (context == null) { @@ -470,25 +478,25 @@ class _TransformerPageViewState extends State { } } + IndexController? _controller; + @override void initState() { _transformer = widget.transformer; // int index = widget.index ?? 0; - _pageController = widget.pageController; - _pageController ??= TransformerPageController( - initialPage: widget.index ?? 0, - itemCount: widget.itemCount, - loop: widget.loop, - reverse: - widget.transformer == null ? false : widget.transformer!.reverse); + _pageController = widget.pageController ?? + TransformerPageController( + initialPage: widget.index ?? 0, + itemCount: widget.itemCount, + loop: widget.loop, + reverse: widget.transformer?.reverse ?? false, + ); // int initPage = _getRealIndexFromRenderIndex(index); // _pageController = PageController(initialPage: initPage,viewportFraction: widget.viewportFraction); - _fromIndex = _activeIndex = _pageController!.initialPage; + _fromIndex = _activeIndex = _pageController.initialPage; - _controller = getNotifier(); - if (_controller != null) { - _controller!.addListener(onChangeNotifier); - } + _controller = widget.controller; + _controller?.addListener(onChangeNotifier); super.initState(); } @@ -499,39 +507,39 @@ class _TransformerPageViewState extends State { var created = false; if (_pageController != widget.pageController) { if (widget.pageController != null) { - _pageController = widget.pageController; + _pageController = widget.pageController!; } else { created = true; _pageController = TransformerPageController( - initialPage: widget.index ?? 0, - itemCount: widget.itemCount, - loop: widget.loop, - reverse: widget.transformer == null - ? false - : widget.transformer!.reverse); + initialPage: widget.index ?? 0, + itemCount: widget.itemCount, + loop: widget.loop, + reverse: widget.transformer?.reverse ?? false, + ); } } - if (_pageController!.getRenderIndexFromRealIndex(_activeIndex) != index) { - _fromIndex = _activeIndex = _pageController!.initialPage; + if (_pageController.getRenderIndexFromRealIndex(_activeIndex) != index) { + _fromIndex = _activeIndex = _pageController.initialPage; if (!created) { - final initPage = _pageController!.getRealIndexFromRenderIndex(index)!; - _pageController!.animateToPage(initPage, - duration: widget.duration, curve: widget.curve); + final initPage = _pageController.getRealIndexFromRenderIndex(index); + if (_pageController.hasClients) { + _pageController.animateToPage( + initPage, + duration: widget.duration, + curve: widget.curve, + ); + } } } if (_transformer != null) { WidgetsBinding.instance!.addPostFrameCallback(_onGetSize); } - if (_controller != getNotifier()) { - if (_controller != null) { - _controller!.removeListener(onChangeNotifier); - } - _controller = getNotifier(); - if (_controller != null) { - _controller!.addListener(onChangeNotifier); - } + if (_controller != widget.controller) { + _controller?.removeListener(onChangeNotifier); + _controller = widget.controller; + _controller?.addListener(onChangeNotifier); } super.didUpdateWidget(oldWidget); } @@ -544,74 +552,44 @@ class _TransformerPageViewState extends State { super.didChangeDependencies(); } - ChangeNotifier? getNotifier() { - return widget.controller; - } - - int _calcNextIndex(bool next) { - var currentIndex = _activeIndex; - if (_pageController!.reverse) { - if (next) { - currentIndex--; - } else { - currentIndex++; - } + void onChangeNotifier() { + final controller = widget.controller!; + final event = controller.event; + int index; + if (event == null) return; + if (event is MoveIndexControllerEvent) { + index = _pageController.getRealIndexFromRenderIndex(event.newIndex); + } else if (event is StepBasedIndexControllerEvent) { + index = event.calcNextIndex( + currentIndex: _activeIndex, + itemCount: _pageController.itemCount, + loop: _pageController.loop, + reverse: _pageController.reverse, + ); } else { - if (next) { - currentIndex++; - } else { - currentIndex--; - } + //ignore other events + return; } - - if (!_pageController!.loop) { - if (currentIndex >= _pageController!.itemCount) { - currentIndex = 0; - } else if (currentIndex < 0) { - currentIndex = _pageController!.itemCount - 1; + if (_pageController.hasClients) { + if (event.animation) { + _pageController + .animateToPage( + index, + duration: widget.duration, + curve: widget.curve, + ) + .whenComplete(event.complete); + } else { + event.complete(); } - } - - return currentIndex; - } - - void onChangeNotifier() { - final event = widget.controller!.event; - var index; - switch (event) { - case IndexController.MOVE: - { - index = _pageController! - .getRealIndexFromRenderIndex(widget.controller!.index!); - } - break; - case IndexController.PREVIOUS: - case IndexController.NEXT: - { - index = _calcNextIndex(event == IndexController.NEXT); - } - break; - default: - //ignore this event - return; - } - if (widget.controller!.animation!) { - _pageController! - .animateToPage(index!, duration: widget.duration, curve: widget.curve) - .whenComplete(widget.controller!.complete); } else { - _pageController!.jumpToPage(index!); - widget.controller!.complete(); + event.complete(); } } - ChangeNotifier? _controller; - @override void dispose() { - if (_controller != null) { - _controller!.removeListener(onChangeNotifier); - } + _controller?.removeListener(onChangeNotifier); super.dispose(); } } diff --git a/pubspec.lock b/pubspec.lock index 69b769e..c7ad8f8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.6.1" + version: "2.8.1" boolean_selector: dependency: transitive description: @@ -28,7 +28,7 @@ packages: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.1" clock: dependency: transitive description: @@ -55,11 +55,32 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: transitive + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_lints_plus: + dependency: "direct dev" + description: + name: flutter_lints_plus + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" matcher: dependency: transitive description: @@ -73,7 +94,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.7.0" path: dependency: transitive description: @@ -81,13 +102,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" - pedantic: - dependency: "direct dev" - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.11.0" sky_engine: dependency: transitive description: flutter @@ -134,7 +148,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.4.2" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 29c0e11..96a09b8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: card_swiper description: swiper/carousel for flutter, with multiple layouts, infinite loop. Compatible with Android & iOS. -version: 1.0.4 +version: 2.0.0 homepage: https://github.com/TheAnkurPanchani/flutter_swiper dependencies: @@ -12,8 +12,8 @@ environment: flutter: ">=0.1.4" dev_dependencies: + flutter_lints_plus: ^1.0.1 flutter_test: sdk: flutter - pedantic: '^1.11.0' - + flutter: diff --git a/test/control_test.dart b/test/control_test.dart index 905d05a..f3e146e 100644 --- a/test/control_test.dart +++ b/test/control_test.dart @@ -1,21 +1,22 @@ +import 'package:card_swiper/card_swiper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:card_swiper/card_swiper.dart'; void main() { - testWidgets('Control horizontal', (WidgetTester tester) async { + testWidgets('Control horizontal', (tester) async { final controller = SwiperController(); final config = SwiperPluginConfig( - activeIndex: 0, - controller: controller, - itemCount: 10, - loop: true, - scrollDirection: Axis.horizontal); + activeIndex: 0, + controller: controller, + itemCount: 10, + loop: true, + scrollDirection: Axis.horizontal, + ); - Key key = UniqueKey(); + final key = UniqueKey(); await tester.pumpWidget(MaterialApp( - home: Scaffold(body: Builder(builder: (BuildContext context) { + home: Scaffold(body: Builder(builder: (context) { return SwiperControl(key: key).build(context, config); })), )); @@ -24,7 +25,7 @@ void main() { var first = true; - await tester.tap(find.byWidgetPredicate((Widget widget) { + await tester.tap(find.byWidgetPredicate((widget) { if (widget is GestureDetector && first) { first = false; return true; @@ -34,7 +35,7 @@ void main() { })); }); - testWidgets('Control vertical', (WidgetTester tester) async { + testWidgets('Control vertical', (tester) async { final controller = SwiperController(); final config = SwiperPluginConfig( @@ -44,9 +45,9 @@ void main() { loop: true, scrollDirection: Axis.vertical); - Key key = UniqueKey(); + final Key key = UniqueKey(); await tester.pumpWidget(MaterialApp( - home: Scaffold(body: Builder(builder: (BuildContext context) { + home: Scaffold(body: Builder(builder: (context) { return SwiperControl( key: key, color: Colors.white, disableColor: Colors.black87) .build(context, config); @@ -57,7 +58,7 @@ void main() { var first = true; - await tester.tap(find.byWidgetPredicate((Widget widget) { + await tester.tap(find.byWidgetPredicate((widget) { if (widget is GestureDetector && first) { first = false; return true; diff --git a/test/flutter_swiper_test.dart b/test/flutter_swiper_test.dart index 6a22540..aa93202 100644 --- a/test/flutter_swiper_test.dart +++ b/test/flutter_swiper_test.dart @@ -1,15 +1,17 @@ +// ignore_for_file: cascade_invocations + +import 'package:card_swiper/card_swiper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:card_swiper/card_swiper.dart'; void main() { - testWidgets('Default Swiper', (WidgetTester tester) async { + testWidgets('Default Swiper', (tester) async { // Build our app and trigger a frame. await tester.pumpWidget( MaterialApp( home: Swiper( itemBuilder: (context, index) { - return Text('0'); + return const Text('0'); }, itemCount: 10, ), @@ -19,13 +21,13 @@ void main() { expect(find.text('0', skipOffstage: false), findsOneWidget); }); - testWidgets('Default Swiper loop:false', (WidgetTester tester) async { + testWidgets('Default Swiper loop:false', (tester) async { // Build our app and trigger a frame. await tester.pumpWidget(MaterialApp( home: Swiper( - onTap: (int inde) {}, + onTap: (index) {}, itemBuilder: (context, index) { - return Text('0'); + return const Text('0'); }, itemCount: 10, loop: false, @@ -34,49 +36,54 @@ void main() { expect(find.text('0', skipOffstage: true), findsOneWidget); }); - testWidgets('Create Swiper with children', (WidgetTester tester) async { + testWidgets('Create Swiper with children', (tester) async { // Build our app and trigger a frame. await tester.pumpWidget(MaterialApp( home: Swiper.children( - children: [Text('0'), Text('1')], + children: const [ + Text('0'), + Text('1'), + ], ))); expect(find.text('0', skipOffstage: false), findsOneWidget); }); - testWidgets('Create Swiper with list', (WidgetTester tester) async { + testWidgets('Create Swiper with list', (tester) async { // Build our app and trigger a frame. await tester.pumpWidget(MaterialApp( - home: Swiper.list( - list: ['0', '1'], - builder: (BuildContext context, dynamic data, int index) { - return Text(data); - }, - ))); + home: Swiper.list( + list: ['0', '1'], + builder: (context, data, index) { + return Text(data); + }, + ), + )); expect(find.text('0', skipOffstage: false), findsOneWidget); }); - testWidgets('Swiper with default plugins', (WidgetTester tester) async { + testWidgets('Swiper with default plugins', (tester) async { // Build our app and trigger a frame. final controller = SwiperController(); await tester.pumpWidget(MaterialApp( - home: Swiper( - controller: controller, - itemBuilder: (context, index) { - return Text('0'); - }, - itemCount: 10, - pagination: SwiperPagination(), - control: SwiperControl(), - ))); + home: Swiper( + controller: controller, + itemBuilder: (context, index) { + return const Text('0'); + }, + itemCount: 10, + pagination: const SwiperPagination(), + control: const SwiperControl(), + ), + )); expect(find.text('0', skipOffstage: false), findsOneWidget); }); const titles = ['Flutter Swiper is awesome', 'Really nice', 'Yeah']; - testWidgets('Customize pagination', (WidgetTester tester) async { + testWidgets('Customize pagination', (tester) async { // Build our app and trigger a frame. final controller = SwiperController(); await tester.pumpWidget( @@ -84,29 +91,28 @@ void main() { home: Swiper( controller: controller, itemBuilder: (context, index) { - return Text('0'); + return const Text('0'); }, itemCount: 10, pagination: SwiperCustomPagination( - builder: (BuildContext context, SwiperPluginConfig? config) { + builder: (context, config) { return ConstrainedBox( - constraints: BoxConstraints.expand(height: 50.0), + constraints: const BoxConstraints.expand(height: 50.0), child: Row( children: [ - if (config != null) - Text( - '${titles[config.activeIndex!]} ${config.activeIndex! + 1}/${config.itemCount}', - style: TextStyle(fontSize: 20.0), - ), + Text( + '${titles[config.activeIndex]} ${config.activeIndex + 1}/${config.itemCount}', + style: const TextStyle(fontSize: 20.0), + ), Expanded( child: Align( alignment: Alignment.centerRight, - child: DotSwiperPaginationBuilder( - color: Colors.black12, - activeColor: Colors.black, - size: 10.0, - activeSize: 20.0) - .build(context, config), + child: const DotSwiperPaginationBuilder( + color: Colors.black12, + activeColor: Colors.black, + size: 10.0, + activeSize: 20.0, + ).build(context, config), ), ) ], @@ -114,7 +120,7 @@ void main() { ); }, ), - control: SwiperControl(), + control: const SwiperControl(), ), ), ); @@ -132,35 +138,36 @@ void main() { expect(find.text('0', skipOffstage: false), findsOneWidget); }); - testWidgets('Swiper fraction', (WidgetTester tester) async { + testWidgets('Swiper fraction', (tester) async { // Build our app and trigger a frame. final controller = SwiperController(); await tester.pumpWidget(MaterialApp( - home: Swiper( - controller: controller, - itemBuilder: (context, index) { - return Text('0'); - }, - itemCount: 10, - pagination: SwiperPagination(builder: SwiperPagination.fraction), - control: SwiperControl(), - ))); + home: Swiper( + controller: controller, + itemBuilder: (context, index) { + return const Text('0'); + }, + itemCount: 10, + pagination: const SwiperPagination(builder: SwiperPagination.fraction), + control: const SwiperControl(), + ), + )); expect(find.text('0', skipOffstage: false), findsOneWidget); }); - testWidgets('Zero itemCount', (WidgetTester tester) async { + testWidgets('Zero itemCount', (tester) async { // Build our app and trigger a frame. final controller = SwiperController(); await tester.pumpWidget(MaterialApp( home: Swiper( controller: controller, itemBuilder: (context, index) { - return Text('0'); + return const Text('0'); }, itemCount: 0, - pagination: SwiperPagination(builder: SwiperPagination.fraction), - control: SwiperControl(), + pagination: const SwiperPagination(builder: SwiperPagination.fraction), + control: const SwiperControl(), ))); expect(find.text('0', skipOffstage: false), findsNothing); diff --git a/test/layout_test.dart b/test/layout_test.dart index bdf2998..3d7b479 100644 --- a/test/layout_test.dart +++ b/test/layout_test.dart @@ -1,9 +1,9 @@ +import 'package:card_swiper/card_swiper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:card_swiper/card_swiper.dart'; void main() { - testWidgets('STACK', (WidgetTester tester) async { + testWidgets('STACK', (tester) async { await tester.pumpWidget( MaterialApp( home: Swiper( @@ -24,7 +24,7 @@ void main() { ); }); - testWidgets('TINDER', (WidgetTester tester) async { + testWidgets('TINDER', (tester) async { await tester.pumpWidget( MaterialApp( home: Swiper( @@ -45,7 +45,7 @@ void main() { ); }); - testWidgets('DEFAULT', (WidgetTester tester) async { + testWidgets('DEFAULT', (tester) async { await tester.pumpWidget( MaterialApp( home: Swiper( @@ -66,11 +66,17 @@ void main() { ); }); - testWidgets('CUSTOM', (WidgetTester tester) async { + testWidgets('CUSTOM', (tester) async { CustomLayoutOption customLayoutOption; customLayoutOption = CustomLayoutOption(startIndex: -1, stateCount: 3) - .addRotate([-45.0 / 180, 0.0, 45.0 / 180]).addTranslate( - [Offset(-370.0, -40.0), Offset(0.0, 0.0), Offset(370.0, -40.0)]); + ..addRotate([-45.0 / 180, 0.0, 45.0 / 180]) + ..addTranslate( + const [ + Offset(-370.0, -40.0), + Offset.zero, + Offset(370.0, -40.0), + ], + ); await tester.pumpWidget( MaterialApp( home: Swiper( diff --git a/test/pagination_test.dart b/test/pagination_test.dart index 05e4dbc..e0fb87e 100644 --- a/test/pagination_test.dart +++ b/test/pagination_test.dart @@ -1,9 +1,9 @@ +import 'package:card_swiper/card_swiper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:card_swiper/card_swiper.dart'; void main() { - testWidgets('Pagination', (WidgetTester tester) async { + testWidgets('Pagination', (tester) async { final controller = SwiperController(); final config = SwiperPluginConfig( @@ -13,34 +13,31 @@ void main() { scrollDirection: Axis.horizontal, ); - Key key = UniqueKey(); + final key = UniqueKey(); await tester.pumpWidget(MaterialApp( - home: Scaffold(body: Builder(builder: (BuildContext context) { + home: Scaffold(body: Builder(builder: (context) { return DotSwiperPaginationBuilder( - key: key, - activeColor: Color(0xff000000), - color: Color(0xffffffff), - space: 10.0, - size: 10.0, - activeSize: 20.0) - .build(context, config); + key: key, + activeColor: const Color(0xff000000), + color: const Color(0xffffffff), + space: 10.0, + size: 10.0, + activeSize: 20.0, + ).build(context, config); })), )); for (var i = 0; i < 10; ++i) { - expect(find.byWidgetPredicate((Widget widget) { - if (widget.key != null && - widget.key is ValueKey && - (widget.key as ValueKey).value == 'pagination_$i') return true; - - return false; + expect(find.byWidgetPredicate((widget) { + final key = widget.key; + return key != null && key is ValueKey && key.value == 'pagination_$i'; }), findsOneWidget); } expect(find.byKey(key), findsOneWidget); }); - testWidgets('Pagination vertical', (WidgetTester tester) async { + testWidgets('Pagination vertical', (tester) async { final controller = SwiperController(); final config = SwiperPluginConfig( @@ -50,13 +47,13 @@ void main() { scrollDirection: Axis.vertical, ); - Key key = UniqueKey(); + final key = UniqueKey(); await tester.pumpWidget(MaterialApp( - home: Scaffold(body: Builder(builder: (BuildContext context) { + home: Scaffold(body: Builder(builder: (context) { return DotSwiperPaginationBuilder( key: key, - activeColor: Color(0xff000000), - color: Color(0xffffffff), + activeColor: const Color(0xff000000), + color: const Color(0xffffffff), space: 10.0, size: 10.0, activeSize: 20.0) @@ -65,19 +62,16 @@ void main() { )); for (var i = 0; i < 10; ++i) { - expect(find.byWidgetPredicate((Widget widget) { - if (widget.key != null && - widget.key is ValueKey && - (widget.key as ValueKey).value == 'pagination_$i') return true; - - return false; + expect(find.byWidgetPredicate((widget) { + final key = widget.key; + return key != null && key is ValueKey && key.value == 'pagination_$i'; }), findsOneWidget); } expect(find.byKey(key), findsOneWidget); }); - testWidgets('Pagination fraction', (WidgetTester tester) async { + testWidgets('Pagination fraction', (tester) async { final controller = SwiperController(); final config = SwiperPluginConfig( @@ -86,13 +80,13 @@ void main() { itemCount: 10, scrollDirection: Axis.horizontal); - Key key = UniqueKey(); + final Key key = UniqueKey(); await tester.pumpWidget(MaterialApp( - home: Scaffold(body: Builder(builder: (BuildContext context) { + home: Scaffold(body: Builder(builder: (context) { return FractionPaginationBuilder( key: key, - activeColor: Color(0xff000000), - color: Color(0xffffffff), + activeColor: const Color(0xff000000), + color: const Color(0xffffffff), ).build(context, config); })), )); @@ -103,7 +97,7 @@ void main() { expect(find.byKey(key), findsOneWidget); }); - testWidgets('Pagination fraction vertical', (WidgetTester tester) async { + testWidgets('Pagination fraction vertical', (tester) async { final controller = SwiperController(); final config = SwiperPluginConfig( @@ -113,13 +107,13 @@ void main() { scrollDirection: Axis.vertical, ); - Key key = UniqueKey(); + final Key key = UniqueKey(); await tester.pumpWidget(MaterialApp( - home: Scaffold(body: Builder(builder: (BuildContext context) { + home: Scaffold(body: Builder(builder: (context) { return FractionPaginationBuilder( key: key, - activeColor: Color(0xff000000), - color: Color(0xffffffff), + activeColor: const Color(0xff000000), + color: const Color(0xffffffff), ).build(context, config); })), ));