diff --git a/.gitignore b/.gitignore index 6dd760e..5904058 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ .idea/ build/ +coverage/ ios/.generated/ ios/Flutter/Generated.xcconfig ios/Runner/GeneratedPluginRegistrant.* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..76de09c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +language: bash +os: + - osx +sudo: false +before_script: + - cd .. + - git clone https://github.com/flutter/flutter.git -b master + - export PATH=$PATH:$PWD/flutter/bin + - export PATH=$PATH:$PWD/flutter/bin/cache/dart-sdk/bin + - flutter doctor + - cd - +script: + # abort on error + - set -e + - flutter packages get + - flutter format --set-exit-if-changed -l 120 lib -l 120 example + - flutter analyze lib example + - flutter test --no-pub --coverage + # export coverage + - bash <(curl -s https://codecov.io/bash) +cache: + directories: + - $HOME/.pub-cache diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e0b07..8b055f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,21 +2,40 @@ A collection of loading indicators animated with flutter. Heavily inspired by @tobiasahlin's SpinKit. +## 4.1.0 + +- Introduces a new SpinKit [SpinKitSquareCircle] +- Introduces `const` SpinKits +- Improve code quality across all spinners + +### Before + +```dart +final spinkit = SpinKitSquareCircle(color: Colors.white, size: 50.0); +``` + +### Now, all SpinKits can be initialized as `const`s + +```dart +const spinkit = SpinKitSquareCircle(color: Colors.white, size: 50.0); +``` + + + ## 4.0.0 ### Feature -- `controller` parameter [20248d](https://github.com/jogboms/flutter_spinkit/commit/20248d2f8bd1056a453a5e57f063e8d59dba9b36). Closes [#51](https://github.com/jogboms/flutter_spinkit/issues/51) +- `controller` parameter [5873e7](https://github.com/jogboms/flutter_spinkit/commit/5873e75430aca52d2ec0c483dcd71a02438f3e8b). Closes [#51](https://github.com/jogboms/flutter_spinkit/issues/51) ```dart -SpinKitFadingCircle( +final spinkit = SpinKitFadingCircle( color: Colors.white, size: 50.0, controller: AnimationController(vsync: this, duration: const Duration(milliseconds: 1200)), ); - ``` -- DualRing `lineWidth` parameter [5873e7](https://github.com/jogboms/flutter_spinkit/commit/5873e75430aca52d2ec0c483dcd71a02438f3e8b). Closes [#42](https://github.com/jogboms/flutter_spinkit/issues/42) +- [DualRing] `lineWidth` parameter [9bcfd5](https://github.com/jogboms/flutter_spinkit/commit/9bcfd507459dfabf50d26a27cdb2c11188fce913). Closes [#42](https://github.com/jogboms/flutter_spinkit/issues/42) ## 3.1.0 @@ -33,16 +52,13 @@ SpinKitFadingCircle( ### Before ```dart -SpinKitFadingCircle( - color: Colors.white, - size: 50.0, -); +final spinkit = SpinKitFadingCircle(color: Colors.white, size: 50.0); ``` ### Now, there is an itemBuilder alternative ```dart -SpinKitFadingCircle( +final spinkit = SpinKitFadingCircle( itemBuilder: (_, int index) { return DecoratedBox( decoration: BoxDecoration( diff --git a/README.md b/README.md index cb9e332..ee52372 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ✨ Flutter Spinkit -[![pub package](https://img.shields.io/pub/v/flutter_spinkit.svg)](https://pub.dartlang.org/packages/flutter_spinkit) +[![Build Status - Travis](https://travis-ci.org/jogboms/flutter_spinkit.svg?branch=master)](https://travis-ci.org/jogboms/flutter_spinkit) [![codecov](https://codecov.io/gh/jogboms/flutter_spinkit/branch/master/graph/badge.svg)](https://codecov.io/gh/jogboms/flutter_spinkit) [![pub package](https://img.shields.io/pub/v/flutter_spinkit.svg)](https://pub.dartlang.org/packages/flutter_spinkit) A collection of loading indicators animated with flutter. Heavily inspired by [@tobiasahlin](https://github.com/tobiasahlin)'s [SpinKit](https://github.com/tobiasahlin/SpinKit). @@ -8,7 +8,7 @@ A collection of loading indicators animated with flutter. Heavily inspired by [@ ```yaml dependencies: - flutter_spinkit: "^4.0.0" + flutter_spinkit: "^4.1.0" ``` ### ⚡️ Import @@ -20,15 +20,15 @@ import 'package:flutter_spinkit/flutter_spinkit.dart'; ## 🎮 How To Use ```dart -SpinKitRotatingCircle( +const spinkit = SpinKitRotatingCircle( color: Colors.white, size: 50.0, ); ``` ```dart -SpinKitFadingCircle( - itemBuilder: (_, int index) { +final spinkit = SpinKitFadingCircle( + itemBuilder: (BuildContext context, int index) { return DecoratedBox( decoration: BoxDecoration( color: index.isEven ? Colors.red : Colors.green, @@ -38,10 +38,8 @@ SpinKitFadingCircle( ); ``` -#### As from 4.0.0 - ```dart -SpinKitFadingCircle( +final spinkit = SpinKitSquareCircle( color: Colors.white, size: 50.0, controller: AnimationController(vsync: this, duration: const Duration(milliseconds: 1200)), @@ -55,164 +53,125 @@ For more info, please, refer to the `showcase.dart` in the example. +
- -
- RotatingPlane +
- ✅ + RotatingPlain
- +
DoubleBounce -
- ✅
- +
Wave -
- ✅
- +
WanderingCubes -
- ✅
- +
FadingFour -
- ✅
- +
FadingCube -
- ✅
- +
Pulse -
- ✅
- +
ChasingDots -
- ✅
- +
ThreeBounce -
- ✅
- +
Circle -
- ✅
- +
CubeGrid -
- ✅
- +
FadingCircle -
- ✅
- +
RotatingCircle -
- ✅
- +
FoldingCube -
- ✅
- +
PumpingHeart -
- ✅
- +
DualRing -
- ✅
- +
HourGlass -
- ✅
- +
PouringHourGlass -
- ✅
- +
FadingGrid -
- ✅
- +
Ring -
- ✅
- +
Ripple -
- ✅
- +
SpinningCircle +
+
- ✅ + SquareCircle
diff --git a/example/ios/.gitignore b/example/ios/.gitignore index 79cc4da..2dd822b 100644 --- a/example/ios/.gitignore +++ b/example/ios/.gitignore @@ -37,6 +37,7 @@ Icon? /Flutter/app.zip /Flutter/flutter_assets/ /Flutter/App.framework +/Flutter/flutter_export_environment.sh /Flutter/Flutter.framework /Flutter/Generated.xcconfig /ServiceDefinitions.json diff --git a/example/lib/showcase.dart b/example/lib/showcase.dart index b48696f..3f55d1b 100644 --- a/example/lib/showcase.dart +++ b/example/lib/showcase.dart @@ -18,92 +18,89 @@ class ShowCase extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitRotatingCircle(color: Colors.white), - SpinKitRotatingPlain(color: Colors.white), - SpinKitChasingDots(color: Colors.white), + const SpinKitRotatingCircle(color: Colors.white), + const SpinKitRotatingPlain(color: Colors.white), + const SpinKitChasingDots(color: Colors.white), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitPumpingHeart(color: Colors.white), - SpinKitPulse(color: Colors.white), - SpinKitDoubleBounce(color: Colors.white), + const SpinKitPumpingHeart(color: Colors.white), + const SpinKitPulse(color: Colors.white), + const SpinKitDoubleBounce(color: Colors.white), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitWave(color: Colors.white, type: SpinKitWaveType.start), - SpinKitWave(color: Colors.white, type: SpinKitWaveType.center), - SpinKitWave(color: Colors.white, type: SpinKitWaveType.end), + const SpinKitWave(color: Colors.white, type: SpinKitWaveType.start), + const SpinKitWave(color: Colors.white, type: SpinKitWaveType.center), + const SpinKitWave(color: Colors.white, type: SpinKitWaveType.end), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitThreeBounce(color: Colors.white), - SpinKitWanderingCubes(color: Colors.white), - SpinKitWanderingCubes( - color: Colors.white, shape: BoxShape.circle), + const SpinKitThreeBounce(color: Colors.white), + const SpinKitWanderingCubes(color: Colors.white), + const SpinKitWanderingCubes(color: Colors.white, shape: BoxShape.circle), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitCircle(color: Colors.white), - SpinKitFadingFour(color: Colors.white), - SpinKitFadingFour( - color: Colors.white, shape: BoxShape.rectangle), + const SpinKitCircle(color: Colors.white), + const SpinKitFadingFour(color: Colors.white), + const SpinKitFadingFour(color: Colors.white, shape: BoxShape.rectangle), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitFadingCube(color: Colors.white), - SpinKitCubeGrid(size: 51.0, color: Colors.white), - SpinKitFoldingCube(color: Colors.white), + const SpinKitFadingCube(color: Colors.white), + const SpinKitCubeGrid(size: 51.0, color: Colors.white), + const SpinKitFoldingCube(color: Colors.white), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitRing(color: Colors.white), - SpinKitDualRing(color: Colors.white), - SpinKitRipple(color: Colors.white), + const SpinKitRing(color: Colors.white), + const SpinKitDualRing(color: Colors.white), + const SpinKitRipple(color: Colors.white), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitFadingGrid(color: Colors.white), - SpinKitFadingGrid( - color: Colors.white, shape: BoxShape.rectangle), - SpinKitHourGlass(color: Colors.white), + const SpinKitFadingGrid(color: Colors.white), + const SpinKitFadingGrid(color: Colors.white, shape: BoxShape.rectangle), + const SpinKitSquareCircle(color: Colors.white), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitSpinningCircle(color: Colors.white), - SpinKitSpinningCircle( - color: Colors.white, shape: BoxShape.rectangle), - SpinKitFadingCircle(color: Colors.white), + const SpinKitSpinningCircle(color: Colors.white), + const SpinKitSpinningCircle(color: Colors.white, shape: BoxShape.rectangle), + const SpinKitFadingCircle(color: Colors.white), ], ), const SizedBox(height: 48.0), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - SpinKitPouringHourglass(color: Colors.white), + const SpinKitHourGlass(color: Colors.white), + const SpinKitPouringHourglass(color: Colors.white), ], ), const SizedBox(height: 64.0), diff --git a/example/pubspec.lock b/example/pubspec.lock index e8fefe9..112e1b5 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,20 +1,34 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" charcode: dependency: transitive description: @@ -29,6 +43,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.14.11" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" flutter: dependency: "direct main" description: flutter @@ -46,6 +74,13 @@ packages: description: flutter source: sdk version: "0.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" matcher: dependency: transitive description: @@ -59,28 +94,35 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.1.7" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" + version: "1.6.4" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0+1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.5" sky_engine: dependency: transitive description: flutter @@ -113,7 +155,7 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" term_glyph: dependency: transitive description: @@ -142,6 +184,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.8" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "3.5.0" sdks: - dart: ">=2.2.2 <3.0.0" + dart: ">=2.5.0 <3.0.0" flutter: ">=0.1.4 <2.0.0" diff --git a/lib/flutter_spinkit.dart b/lib/flutter_spinkit.dart index bdbff50..4080da6 100644 --- a/lib/flutter_spinkit.dart +++ b/lib/flutter_spinkit.dart @@ -19,6 +19,7 @@ export 'src/ripple.dart'; export 'src/rotating_circle.dart'; export 'src/rotating_plain.dart'; export 'src/spinning_circle.dart'; +export 'src/square_circle.dart'; export 'src/three_bounce.dart'; export 'src/wandering_cubes.dart'; export 'src/wave.dart'; diff --git a/lib/src/chasing_dots.dart b/lib/src/chasing_dots.dart index 55da72b..f997ece 100644 --- a/lib/src/chasing_dots.dart +++ b/lib/src/chasing_dots.dart @@ -1,16 +1,14 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_spinkit/src/utils.dart'; class SpinKitChasingDots extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitChasingDots({ + const SpinKitChasingDots({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 2000), - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -24,35 +22,24 @@ class SpinKitChasingDots extends StatefulWidget { _SpinKitChasingDotsState createState() => _SpinKitChasingDotsState(); } -class _SpinKitChasingDotsState extends State - with TickerProviderStateMixin { +class _SpinKitChasingDotsState extends State with TickerProviderStateMixin { AnimationController _scaleCtrl, _rotateCtrl; Animation _scale, _rotate; @override void initState() { super.initState(); - _scaleCtrl = AnimationController(vsync: this, duration: widget.duration); - _rotateCtrl = AnimationController(vsync: this, duration: widget.duration); - _scale = Tween(begin: -1.0, end: 1.0).animate( - CurvedAnimation(parent: _scaleCtrl, curve: Curves.easeInOut), - ) + _scaleCtrl = AnimationController(vsync: this, duration: widget.duration) ..addListener(() => setState(() {})) - ..addStatusListener((status) { - if (status == AnimationStatus.completed) { - _scaleCtrl.reverse(); - } else if (status == AnimationStatus.dismissed) { - _scaleCtrl.forward(); - } - }); + ..addStatusListener(autoReverseFn(() => _scaleCtrl)) + ..forward(); + _scale = Tween(begin: -1.0, end: 1.0).animate(CurvedAnimation(parent: _scaleCtrl, curve: Curves.easeInOut)); - _rotate = Tween(begin: 0.0, end: 360.0).animate( - CurvedAnimation(parent: _rotateCtrl, curve: Curves.linear), - )..addListener(() => setState(() {})); - - _rotateCtrl.repeat(); - _scaleCtrl.forward(); + _rotateCtrl = AnimationController(vsync: this, duration: widget.duration) + ..addListener(() => setState(() {})) + ..repeat(); + _rotate = Tween(begin: 0.0, end: 360.0).animate(CurvedAnimation(parent: _rotateCtrl, curve: Curves.linear)); } @override @@ -71,14 +58,8 @@ class _SpinKitChasingDotsState extends State angle: _rotate.value * 0.0174533, child: Stack( children: [ - Positioned( - top: 0.0, - child: _circle(1.0 - _scale.value.abs(), 0), - ), - Positioned( - bottom: 0.0, - child: _circle(_scale.value.abs(), 1), - ), + Positioned(top: 0.0, child: _circle(1.0 - _scale.value.abs(), 0)), + Positioned(bottom: 0.0, child: _circle(_scale.value.abs(), 1)), ], ), ), @@ -86,25 +67,15 @@ class _SpinKitChasingDotsState extends State ); } - Widget _itemBuilder(int index) { - final _size = widget.size * 0.6; - return SizedBox.fromSize( - size: Size.square(_size), - child: widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: widget.color, - ), - ), - ); - } - Widget _circle(double scale, int index) { return Transform.scale( scale: scale, - child: _itemBuilder(index), + child: SizedBox.fromSize( + size: Size.square(widget.size * 0.6), + child: widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color)), + ), ); } } diff --git a/lib/src/circle.dart b/lib/src/circle.dart index 150b5f8..54c731d 100644 --- a/lib/src/circle.dart +++ b/lib/src/circle.dart @@ -2,17 +2,14 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; class SpinKitCircle extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitCircle({ + const SpinKitCircle({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -27,16 +24,15 @@ class SpinKitCircle extends StatefulWidget { _SpinKitCircleState createState() => _SpinKitCircleState(); } -class _SpinKitCircleState extends State - with SingleTickerProviderStateMixin { +class _SpinKitCircleState extends State with SingleTickerProviderStateMixin { + final List delays = [.0, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1]; AnimationController _controller; @override void initState() { super.initState(); - _controller = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override @@ -51,56 +47,29 @@ class _SpinKitCircleState extends State child: SizedBox.fromSize( size: Size.square(widget.size), child: Stack( - children: [ - _circle(1, .0), - _circle(2, -1.1), - _circle(3, -1.0), - _circle(4, -0.9), - _circle(5, -0.8), - _circle(6, -0.7), - _circle(7, -0.6), - _circle(8, -0.5), - _circle(9, -0.4), - _circle(10, -0.3), - _circle(11, -0.2), - _circle(12, -0.1), - ], - ), - ), - ); - } - - Widget _circle(int i, [double delay]) { - final _size = widget.size * 0.15, _position = widget.size * .5; - - return Positioned.fill( - left: _position, - top: _position, - child: Transform( - transform: Matrix4.rotationZ(30.0 * (i - 1) * 0.0174533), - child: Align( - alignment: Alignment.center, - child: ScaleTransition( - scale: DelayTween(begin: 0.0, end: 1.0, delay: delay) - .animate(_controller), - child: _itemBuilder(i - 1, _size), - ), + children: List.generate(delays.length, (index) { + final _position = widget.size * .5; + return Positioned.fill( + left: _position, + top: _position, + child: Transform( + transform: Matrix4.rotationZ(30.0 * index * 0.0174533), + child: Align( + alignment: Alignment.center, + child: ScaleTransition( + scale: DelayTween(begin: 0.0, end: 1.0, delay: delays[index]).animate(_controller), + child: SizedBox.fromSize(size: Size.square(widget.size * 0.15), child: _itemBuilder(index)), + ), + ), + ), + ); + }), ), ), ); } - Widget _itemBuilder(int index, double _size) { - return SizedBox.fromSize( - size: Size.square(_size), - child: widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: BoxShape.circle, - ), - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: BoxShape.circle)); } diff --git a/lib/src/cube_grid.dart b/lib/src/cube_grid.dart index ed5225f..3abb6fa 100644 --- a/lib/src/cube_grid.dart +++ b/lib/src/cube_grid.dart @@ -1,17 +1,15 @@ import 'package:flutter/widgets.dart'; +import 'package:flutter_spinkit/src/utils.dart'; class SpinKitCubeGrid extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitCubeGrid({ + const SpinKitCubeGrid({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -26,62 +24,27 @@ class SpinKitCubeGrid extends StatefulWidget { _SpinKitCubeGridState createState() => _SpinKitCubeGridState(); } -class _SpinKitCubeGridState extends State - with SingleTickerProviderStateMixin { +class _SpinKitCubeGridState extends State with SingleTickerProviderStateMixin { AnimationController _controller; Animation _anim1, _anim2, _anim3, _anim4, _anim5; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _anim1 = Tween(begin: 1.0, end: 0.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.1, 0.6, curve: Curves.easeIn), - ), - ); - - _anim2 = Tween(begin: 1.0, end: 0.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.2, 0.7, curve: Curves.easeIn), - ), - ); - - _anim3 = Tween(begin: 1.0, end: 0.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.3, 0.8, curve: Curves.easeIn), - ), - ); - - _anim4 = Tween(begin: 1.0, end: 0.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.4, 0.9, curve: Curves.easeIn), - ), - ); - - _anim5 = Tween(begin: 1.0, end: 0.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.5, 1.0, curve: Curves.easeIn), - ), - ); - _controller - ..addStatusListener((status) { - if (status == AnimationStatus.completed) { - _controller.reverse(); - } - if (status == AnimationStatus.dismissed) { - _controller.forward(); - } - }); - - _controller.forward(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addStatusListener(autoReverseFn(() => _controller)) + ..forward(); + _anim1 = Tween(begin: 1.0, end: 0.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.1, 0.6, curve: Curves.easeIn))); + _anim2 = Tween(begin: 1.0, end: 0.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.2, 0.7, curve: Curves.easeIn))); + _anim3 = Tween(begin: 1.0, end: 0.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.3, 0.8, curve: Curves.easeIn))); + _anim4 = Tween(begin: 1.0, end: 0.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.4, 0.9, curve: Curves.easeIn))); + _anim5 = Tween(begin: 1.0, end: 0.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.5, 1.0, curve: Curves.easeIn))); } @override @@ -133,20 +96,11 @@ class _SpinKitCubeGridState extends State Widget _square(Animation animation, int index) { return ScaleTransition( scale: animation, - child: _itemBuilder(index), + child: SizedBox.fromSize(size: Size.square(widget.size / 3), child: _itemBuilder(index)), ); } - Widget _itemBuilder(int index) { - return SizedBox.fromSize( - size: Size.square(widget.size / 3), - child: widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - ), - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color)); } diff --git a/lib/src/double_bounce.dart b/lib/src/double_bounce.dart index 966e0a8..5068511 100644 --- a/lib/src/double_bounce.dart +++ b/lib/src/double_bounce.dart @@ -1,17 +1,15 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_spinkit/src/utils.dart'; class SpinKitDoubleBounce extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitDoubleBounce({ + const SpinKitDoubleBounce({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 2000), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -26,35 +24,19 @@ class SpinKitDoubleBounce extends StatefulWidget { _SpinKitDoubleBounceState createState() => _SpinKitDoubleBounceState(); } -class _SpinKitDoubleBounceState extends State - with SingleTickerProviderStateMixin { +class _SpinKitDoubleBounceState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _animation1; - - void _statusListener(AnimationStatus status) { - if (status == AnimationStatus.completed) { - _controller.reverse(); - } else if (status == AnimationStatus.dismissed) { - _controller.forward(); - } - } + Animation _animation; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: -1.0, end: 1.0).animate( - CurvedAnimation( - parent: _controller, - curve: Curves.easeInOut, - ), - ) + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) ..addListener(() => setState(() {})) - ..addStatusListener(_statusListener); - - _controller.forward(); + ..addStatusListener(autoReverseFn(() => _controller)) + ..forward(); + _animation = Tween(begin: -1.0, end: 1.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)); } @override @@ -67,31 +49,17 @@ class _SpinKitDoubleBounceState extends State Widget build(BuildContext context) { return Center( child: Stack( - children: [ - Transform.scale( - scale: 1.0 - _animation1.value.abs(), - child: _itemBuilder(0), - ), - Transform.scale( - scale: _animation1.value.abs(), - child: _itemBuilder(1), - ), - ], + children: List.generate(2, (i) { + return Transform.scale( + scale: (1.0 - i - _animation.value).abs(), + child: SizedBox.fromSize(size: Size.square(widget.size), child: _itemBuilder(i)), + ); + }), ), ); } - Widget _itemBuilder(int index) { - return SizedBox.fromSize( - size: Size.square(widget.size), - child: widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: widget.color.withOpacity(0.6), - ), - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color.withOpacity(0.6))); } diff --git a/lib/src/dual_ring.dart b/lib/src/dual_ring.dart index 85f4692..becc6b7 100644 --- a/lib/src/dual_ring.dart +++ b/lib/src/dual_ring.dart @@ -3,8 +3,7 @@ import 'dart:math' as math; import 'package:flutter/widgets.dart'; class SpinKitDualRing extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitDualRing({ + const SpinKitDualRing({ Key key, @required this.color, this.lineWidth = 7.0, @@ -25,24 +24,19 @@ class SpinKitDualRing extends StatefulWidget { _SpinKitDualRingState createState() => _SpinKitDualRingState(); } -class _SpinKitDualRingState extends State - with SingleTickerProviderStateMixin { +class _SpinKitDualRingState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _animation1; + Animation _animation; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 1.0, curve: Curves.linear), - ), - )..addListener(() => setState(() {})); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation = Tween(begin: 0.0, end: 1.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: Curves.linear))); } @override @@ -53,20 +47,13 @@ class _SpinKitDualRingState extends State @override Widget build(BuildContext context) { - final Matrix4 transform = Matrix4.identity() - ..rotateZ((_animation1.value) * math.pi * 2); return Center( child: Transform( - transform: transform, + transform: Matrix4.identity()..rotateZ((_animation.value) * math.pi * 2), alignment: FractionalOffset.center, child: CustomPaint( - child: SizedBox.fromSize( - size: Size.square(widget.size), - ), - painter: _DualRingPainter( - paintWidth: widget.lineWidth, - color: widget.color, - ), + child: SizedBox.fromSize(size: Size.square(widget.size)), + painter: _DualRingPainter(paintWidth: widget.lineWidth, color: widget.color), ), ), ); @@ -74,11 +61,8 @@ class _SpinKitDualRingState extends State } class _DualRingPainter extends CustomPainter { - _DualRingPainter({ - this.angle = 90.0, - double paintWidth, - Color color, - }) : ringPaint = Paint() + _DualRingPainter({this.angle = 90.0, double paintWidth, Color color}) + : ringPaint = Paint() ..color = color ..strokeWidth = paintWidth ..style = PaintingStyle.stroke; @@ -96,7 +80,5 @@ class _DualRingPainter extends CustomPainter { @override bool shouldRepaint(CustomPainter oldDelegate) => true; - double getRadian(double angle) { - return math.pi / 180 * angle; - } + double getRadian(double angle) => math.pi / 180 * angle; } diff --git a/lib/src/fading_circle.dart b/lib/src/fading_circle.dart index 25553e2..4c3816f 100644 --- a/lib/src/fading_circle.dart +++ b/lib/src/fading_circle.dart @@ -2,17 +2,14 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; class SpinKitFadingCircle extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitFadingCircle({ + const SpinKitFadingCircle({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -27,16 +24,15 @@ class SpinKitFadingCircle extends StatefulWidget { _SpinKitFadingCircleState createState() => _SpinKitFadingCircleState(); } -class _SpinKitFadingCircleState extends State - with SingleTickerProviderStateMixin { +class _SpinKitFadingCircleState extends State with SingleTickerProviderStateMixin { + final List delays = [.0, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1]; AnimationController _controller; @override void initState() { super.initState(); - _controller = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override @@ -51,56 +47,29 @@ class _SpinKitFadingCircleState extends State child: SizedBox.fromSize( size: Size.square(widget.size), child: Stack( - children: [ - _circle(1, .0), - _circle(2, -1.1), - _circle(3, -1.0), - _circle(4, -0.9), - _circle(5, -0.8), - _circle(6, -0.7), - _circle(7, -0.6), - _circle(8, -0.5), - _circle(9, -0.4), - _circle(10, -0.3), - _circle(11, -0.2), - _circle(12, -0.1), - ], - ), - ), - ); - } - - Widget _circle(int i, [double delay]) { - final _size = widget.size * 0.15, _position = widget.size * .5; - - return Positioned.fill( - left: _position, - top: _position, - child: Transform( - transform: Matrix4.rotationZ(30.0 * (i - 1) * 0.0174533), - child: Align( - alignment: Alignment.center, - child: FadeTransition( - opacity: DelayTween(begin: 0.0, end: 1.0, delay: delay) - .animate(_controller), - child: SizedBox.fromSize( - size: Size.square(_size), - child: _itemBuilder(i - 1), - ), - ), + children: List.generate(12, (i) { + final _position = widget.size * .5; + return Positioned.fill( + left: _position, + top: _position, + child: Transform( + transform: Matrix4.rotationZ(30.0 * i * 0.0174533), + child: Align( + alignment: Alignment.center, + child: FadeTransition( + opacity: DelayTween(begin: 0.0, end: 1.0, delay: delays[i]).animate(_controller), + child: SizedBox.fromSize(size: Size.square(widget.size * 0.15), child: _itemBuilder(i)), + ), + ), + ), + ); + }), ), ), ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: BoxShape.circle, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: BoxShape.circle)); } diff --git a/lib/src/fading_cube.dart b/lib/src/fading_cube.dart index 104440d..fb53e21 100644 --- a/lib/src/fading_cube.dart +++ b/lib/src/fading_cube.dart @@ -2,17 +2,14 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; class SpinKitFadingCube extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitFadingCube({ + const SpinKitFadingCube({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 2400), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -27,21 +24,19 @@ class SpinKitFadingCube extends StatefulWidget { _SpinKitFadingCubeState createState() => _SpinKitFadingCubeState(); } -class _SpinKitFadingCubeState extends State - with TickerProviderStateMixin { - AnimationController _opacityCtrl; +class _SpinKitFadingCubeState extends State with TickerProviderStateMixin { + AnimationController _controller; @override void initState() { super.initState(); - _opacityCtrl = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override void dispose() { - _opacityCtrl.dispose(); + _controller.dispose(); super.dispose(); } @@ -54,12 +49,27 @@ class _SpinKitFadingCubeState extends State child: Transform.rotate( angle: -45.0 * 0.0174533, child: Stack( - children: [ - _cube(1), - _cube(2), - _cube(3), - _cube(4), - ], + children: List.generate(4, (i) { + final _size = widget.size * 0.5, _position = widget.size * .5; + return Positioned.fill( + top: _position, + left: _position, + child: Transform.scale( + scale: 1.1, + origin: Offset(-_size * .5, -_size * .5), + child: Transform( + transform: Matrix4.rotationZ(90.0 * i * 0.0174533), + child: Align( + alignment: Alignment.center, + child: FadeTransition( + opacity: DelayTween(begin: 0.0, end: 1.0, delay: 0.3 * i).animate(_controller), + child: SizedBox.fromSize(size: Size.square(_size), child: _itemBuilder(i)), + ), + ), + ), + ), + ); + }), ), ), ), @@ -67,40 +77,7 @@ class _SpinKitFadingCubeState extends State ); } - Widget _cube(int i) { - final _size = widget.size * 0.5, _position = widget.size * .5; - - return Positioned.fill( - top: _position, - left: _position, - child: Transform.scale( - scale: 1.1, - origin: Offset(-_size * .5, -_size * .5), - child: Transform( - transform: Matrix4.rotationZ(90.0 * (i - 1) * 0.0174533), - child: Align( - alignment: Alignment.center, - child: FadeTransition( - opacity: DelayTween(begin: 0.0, end: 1.0, delay: 0.3 * (i - 1)) - .animate(_opacityCtrl), - child: SizedBox.fromSize( - size: Size.square(_size), - child: _itemBuilder(i - 1), - ), - ), - ), - ), - ), - ); - } - - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color)); } diff --git a/lib/src/fading_four.dart b/lib/src/fading_four.dart index 6c6b12c..e5d77a3 100644 --- a/lib/src/fading_four.dart +++ b/lib/src/fading_four.dart @@ -2,8 +2,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; class SpinKitFadingFour extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitFadingFour({ + const SpinKitFadingFour({ Key key, this.color, this.shape = BoxShape.circle, @@ -11,9 +10,7 @@ class SpinKitFadingFour extends StatefulWidget { this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(shape != null), assert(size != null), @@ -30,16 +27,15 @@ class SpinKitFadingFour extends StatefulWidget { _SpinKitFadingFourState createState() => _SpinKitFadingFourState(); } -class _SpinKitFadingFourState extends State - with SingleTickerProviderStateMixin { +class _SpinKitFadingFourState extends State with SingleTickerProviderStateMixin { + final List delays = [.0, -0.9, -0.6, -0.3]; AnimationController _controller; @override void initState() { super.initState(); - _controller = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override @@ -54,48 +50,29 @@ class _SpinKitFadingFourState extends State child: SizedBox.fromSize( size: Size.square(widget.size), child: Stack( - children: [ - _circle(0, 1, .0), - _circle(1, 4, -0.9), - _circle(2, 7, -0.6), - _circle(3, 10, -0.3), - ], - ), - ), - ); - } - - Widget _circle(int index, int i, [double delay]) { - final _size = widget.size * 0.25, _position = widget.size * .5; - - return Positioned.fill( - left: _position, - top: _position, - child: Transform( - transform: Matrix4.rotationZ(30.0 * (i - 1) * 0.0174533), - child: Align( - alignment: Alignment.center, - child: FadeTransition( - opacity: DelayTween(begin: 0.0, end: 1.0, delay: delay) - .animate(_controller), - child: SizedBox.fromSize( - size: Size.square(_size), - child: _itemBuilder(index), - ), - ), + children: List.generate(4, (i) { + final _position = widget.size * .5; + return Positioned.fill( + left: _position, + top: _position, + child: Transform( + transform: Matrix4.rotationZ(30.0 * (i * 2) * 0.0174533), + child: Align( + alignment: Alignment.center, + child: FadeTransition( + opacity: DelayTween(begin: 0.0, end: 1.0, delay: delays[i]).animate(_controller), + child: SizedBox.fromSize(size: Size.square(widget.size * 0.25), child: _itemBuilder(i)), + ), + ), + ), + ); + }), ), ), ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: widget.shape, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: widget.shape)); } diff --git a/lib/src/fading_grid.dart b/lib/src/fading_grid.dart index aa2d6fa..4b23d14 100644 --- a/lib/src/fading_grid.dart +++ b/lib/src/fading_grid.dart @@ -2,8 +2,7 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; class SpinKitFadingGrid extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitFadingGrid({ + const SpinKitFadingGrid({ Key key, this.color, this.shape = BoxShape.circle, @@ -11,9 +10,7 @@ class SpinKitFadingGrid extends StatefulWidget { this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(shape != null), assert(size != null), @@ -30,16 +27,14 @@ class SpinKitFadingGrid extends StatefulWidget { _SpinKitFadingGridState createState() => _SpinKitFadingGridState(); } -class _SpinKitFadingGridState extends State - with SingleTickerProviderStateMixin { +class _SpinKitFadingGridState extends State with SingleTickerProviderStateMixin { AnimationController _controller; @override void initState() { super.initState(); - _controller = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override @@ -61,13 +56,9 @@ class _SpinKitFadingGridState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ _circle(0, 1), - SizedBox( - width: widget.size / 8, - ), + SizedBox(width: widget.size / 8), _circle(1, 1), - SizedBox( - width: widget.size / 8, - ), + SizedBox(width: widget.size / 8), _circle(2, 2), ], ), @@ -75,10 +66,7 @@ class _SpinKitFadingGridState extends State mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( - height: widget.size / 8, - width: widget.size, - ), + SizedBox(height: widget.size / 8, width: widget.size), ], ), Row( @@ -86,13 +74,9 @@ class _SpinKitFadingGridState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ _circle(3, 4), - SizedBox( - width: widget.size / 8, - ), + SizedBox(width: widget.size / 8), _circle(4, 1), - SizedBox( - width: widget.size / 8, - ), + SizedBox(width: widget.size / 8), _circle(5, 2), ], ), @@ -100,10 +84,7 @@ class _SpinKitFadingGridState extends State mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( - height: widget.size / 8, - width: widget.size, - ), + SizedBox(height: widget.size / 8, width: widget.size), ], ), Row( @@ -111,13 +92,9 @@ class _SpinKitFadingGridState extends State mainAxisAlignment: MainAxisAlignment.center, children: [ _circle(6, 4), - SizedBox( - width: widget.size / 8, - ), + SizedBox(width: widget.size / 8), _circle(7, 3), - SizedBox( - width: widget.size / 8, - ), + SizedBox(width: widget.size / 8), _circle(8, 3), ], ), @@ -128,8 +105,7 @@ class _SpinKitFadingGridState extends State Widget _circle(int index, int i) { return FadeTransition( - opacity: DelayTween(begin: 0.4, end: 0.9, delay: 0.3 * (i - 1)) - .animate(_controller), + opacity: DelayTween(begin: 0.4, end: 0.9, delay: 0.3 * (i - 1)).animate(_controller), child: SizedBox.fromSize( size: Size.square(widget.size / 4), child: _itemBuilder(index), @@ -137,14 +113,7 @@ class _SpinKitFadingGridState extends State ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: widget.shape, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: widget.shape)); } diff --git a/lib/src/folding_cube.dart b/lib/src/folding_cube.dart index dd1358d..fc0ed38 100644 --- a/lib/src/folding_cube.dart +++ b/lib/src/folding_cube.dart @@ -1,17 +1,15 @@ import 'package:flutter/widgets.dart'; +import 'package:flutter_spinkit/src/utils.dart'; class SpinKitFoldingCube extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitFoldingCube({ + const SpinKitFoldingCube({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 2400), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -26,61 +24,31 @@ class SpinKitFoldingCube extends StatefulWidget { _SpinKitFoldingCubeState createState() => _SpinKitFoldingCubeState(); } -class _SpinKitFoldingCubeState extends State - with SingleTickerProviderStateMixin { - AnimationController _rotateCtrl; +class _SpinKitFoldingCubeState extends State with SingleTickerProviderStateMixin { + AnimationController _controller; Animation _rotate1, _rotate2, _rotate3, _rotate4; @override void initState() { super.initState(); - _rotateCtrl = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _rotateCtrl - ..addStatusListener((status) { - if (status == AnimationStatus.completed) { - _rotateCtrl.reverse(); - } - if (status == AnimationStatus.dismissed) { - _rotateCtrl.forward(); - } - }); - - _rotate1 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _rotateCtrl, - curve: const Interval(0.0, 0.25, curve: Curves.easeIn), - ), - )..addListener(() => setState(() {})); - - _rotate2 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _rotateCtrl, - curve: const Interval(0.25, 0.5, curve: Curves.easeIn), - ), - )..addListener(() => setState(() {})); - - _rotate3 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _rotateCtrl, - curve: const Interval(0.5, 0.75, curve: Curves.easeIn), - ), - )..addListener(() => setState(() {})); - - _rotate4 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _rotateCtrl, - curve: const Interval(0.75, 1.0, curve: Curves.easeIn), - ), - )..addListener(() => setState(() {})); - - _rotateCtrl.forward(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..addStatusListener(autoReverseFn(() => _controller)) + ..forward(); + _rotate1 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 0.25, curve: Curves.easeIn))); + _rotate2 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.25, 0.5, curve: Curves.easeIn))); + _rotate3 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.5, 0.75, curve: Curves.easeIn))); + _rotate4 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.75, 1.0, curve: Curves.easeIn))); } @override void dispose() { - _rotateCtrl.dispose(); + _controller.dispose(); super.dispose(); } @@ -109,8 +77,7 @@ class _SpinKitFoldingCubeState extends State Widget _cube(int i, {Animation animation}) { final _size = widget.size * 0.5, _position = widget.size * .5; - final Matrix4 _tRotate = Matrix4.identity() - ..rotateY(animation.value * 0.0174533); + final Matrix4 _tRotate = Matrix4.identity()..rotateY(animation.value * 0.0174533); return Positioned.fill( top: _position, @@ -135,13 +102,7 @@ class _SpinKitFoldingCubeState extends State ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color)); } diff --git a/lib/src/hour_glass.dart b/lib/src/hour_glass.dart index c7fe6c6..d0abef7 100644 --- a/lib/src/hour_glass.dart +++ b/lib/src/hour_glass.dart @@ -22,24 +22,19 @@ class SpinKitHourGlass extends StatefulWidget { _SpinKitHourGlassState createState() => _SpinKitHourGlassState(); } -class _SpinKitHourGlassState extends State - with SingleTickerProviderStateMixin { +class _SpinKitHourGlassState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _animation1; + Animation _animation; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: 0.0, end: 8.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 1.0, curve: Curves.easeOut), - ), - )..addListener(() => setState(() {})); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation = Tween(begin: 0.0, end: 8.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: Curves.easeOut))); } @override @@ -50,16 +45,12 @@ class _SpinKitHourGlassState extends State @override Widget build(BuildContext context) { - final Matrix4 transform = Matrix4.identity() - ..rotateZ((_animation1.value) * math.pi); return Center( child: Transform( - transform: transform, + transform: Matrix4.identity()..rotateZ((_animation.value) * math.pi), alignment: FractionalOffset.center, child: CustomPaint( - child: SizedBox.fromSize( - size: Size.square(widget.size), - ), + child: SizedBox.fromSize(size: Size.square(widget.size)), painter: _HourGlassPainter(color: widget.color), ), ), @@ -68,36 +59,23 @@ class _SpinKitHourGlassState extends State } class _HourGlassPainter extends CustomPainter { - _HourGlassPainter({this.weight = 90.0, Color color}) { - p.color = color; - p.strokeWidth = 1.0; - } + _HourGlassPainter({this.weight = 90.0, Color color}) + : _paint = Paint() + ..color = color + ..strokeWidth = 1.0; - Paint p = Paint(); + final Paint _paint; final double weight; @override void paint(Canvas canvas, Size size) { - canvas.drawArc( - Rect.fromPoints(Offset.zero, Offset(size.width, size.height)), - 0.0, - getRadian(weight), - true, - p, - ); - canvas.drawArc( - Rect.fromPoints(Offset.zero, Offset(size.width, size.height)), - getRadian(180.0), - getRadian(weight), - true, - p, - ); + final rect = Rect.fromPoints(Offset.zero, Offset(size.width, size.height)); + canvas.drawArc(rect, 0.0, getRadian(weight), true, _paint); + canvas.drawArc(rect, getRadian(180.0), getRadian(weight), true, _paint); } @override bool shouldRepaint(CustomPainter oldDelegate) => true; - double getRadian(double angle) { - return math.pi / 180 * angle; - } + double getRadian(double angle) => math.pi / 180 * angle; } diff --git a/lib/src/pouring_hour_glass.dart b/lib/src/pouring_hour_glass.dart index f103781..103e2a9 100644 --- a/lib/src/pouring_hour_glass.dart +++ b/lib/src/pouring_hour_glass.dart @@ -20,33 +20,24 @@ class SpinKitPouringHourglass extends StatefulWidget { final AnimationController controller; @override - _SpinKitPouringHourglassState createState() => - _SpinKitPouringHourglassState(); + _SpinKitPouringHourglassState createState() => _SpinKitPouringHourglassState(); } -class _SpinKitPouringHourglassState extends State - with SingleTickerProviderStateMixin { +class _SpinKitPouringHourglassState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _pouringAnimation; - - Animation _rotationAnimation; + Animation _pouringAnimation, _rotationAnimation; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _pouringAnimation = CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 0.9), - )..addListener(_repaint); - _rotationAnimation = Tween(begin: 0.0, end: 0.5).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.9, 1.0, curve: Curves.fastOutSlowIn), - ), - )..addListener(_repaint); - _controller.repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _pouringAnimation = CurvedAnimation(parent: _controller, curve: const Interval(0.0, 0.9)) + ..addListener(() => setState(() {})); + _rotationAnimation = Tween(begin: 0.0, end: 0.5) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.9, 1.0, curve: Curves.fastOutSlowIn))); } @override @@ -72,15 +63,11 @@ class _SpinKitPouringHourglassState extends State ), ); } - - void _repaint() => this.setState(() {}); } class _HourGlassPaint extends CustomPainter { - _HourGlassPaint({ - this.poured, - @required Color color, - }) : _paint = Paint() + _HourGlassPaint({this.poured, @required Color color}) + : _paint = Paint() ..style = PaintingStyle.stroke ..color = color, _powderPaint = Paint() @@ -114,14 +101,8 @@ class _HourGlassPaint extends CustomPainter { final upperPart = Path() ..moveTo(0.0, top) - ..addRect( - Rect.fromLTRB(0.0, halfHeight * poured, size.width, halfHeight), - ); - - canvas.drawPath( - Path.combine(PathOperation.intersect, hourglassPath, upperPart), - _powderPaint, - ); + ..addRect(Rect.fromLTRB(0.0, halfHeight * poured, size.width, halfHeight)); + canvas.drawPath(Path.combine(PathOperation.intersect, hourglassPath, upperPart), _powderPaint); final lowerPartPath = Path() ..moveTo(centerX, bottom) @@ -129,21 +110,14 @@ class _HourGlassPaint extends CustomPainter { ..lineTo(centerX, bottom - poured * halfHeight - gapWidth) ..lineTo(centerX - hourglassWidth * poured, bottom) ..close(); - final lowerPart = Path.combine( PathOperation.intersect, lowerPartPath, - Path() - ..addRect( - Rect.fromLTRB(0.0, halfHeight, size.width, size.height), - ), + Path()..addRect(Rect.fromLTRB(0.0, halfHeight, size.width, size.height)), ); canvas.drawPath(lowerPart, _powderPaint); - canvas.drawLine( - Offset(centerX, halfHeight), - Offset(centerX, bottom), - _paint, - ); + + canvas.drawLine(Offset(centerX, halfHeight), Offset(centerX, bottom), _paint); } @override diff --git a/lib/src/pulse.dart b/lib/src/pulse.dart index b2308f7..3750210 100644 --- a/lib/src/pulse.dart +++ b/lib/src/pulse.dart @@ -1,17 +1,14 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; class SpinKitPulse extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitPulse({ + const SpinKitPulse({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(seconds: 1), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -26,22 +23,18 @@ class SpinKitPulse extends StatefulWidget { _SpinKitPulseState createState() => _SpinKitPulseState(); } -class _SpinKitPulseState extends State - with SingleTickerProviderStateMixin { +class _SpinKitPulseState extends State with SingleTickerProviderStateMixin { AnimationController _controller; Animation _animation; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation = CurveTween(curve: Curves.easeInOut).animate(_controller) - ..addListener( - () => setState(() {}), - ); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation = CurveTween(curve: Curves.easeInOut).animate(_controller); } @override @@ -66,14 +59,7 @@ class _SpinKitPulseState extends State ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: widget.color, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(shape: BoxShape.circle, color: widget.color)); } diff --git a/lib/src/pumping_heart.dart b/lib/src/pumping_heart.dart index e468134..7207f1c 100644 --- a/lib/src/pumping_heart.dart +++ b/lib/src/pumping_heart.dart @@ -1,20 +1,17 @@ import 'dart:math'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' show Icons; import 'package:flutter/widgets.dart'; class SpinKitPumpingHeart extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitPumpingHeart({ + const SpinKitPumpingHeart({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 2400), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -29,21 +26,17 @@ class SpinKitPumpingHeart extends StatefulWidget { _SpinKitPumpingHeartState createState() => _SpinKitPumpingHeartState(); } -class _SpinKitPumpingHeartState extends State - with SingleTickerProviderStateMixin { +class _SpinKitPumpingHeartState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _anim1; + Animation _animation; @override void initState() { super.initState(); - _controller = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); - _anim1 = Tween(begin: 1.0, end: 1.25).animate(CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 1.0, curve: MyCurve()), - )); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); + _animation = Tween(begin: 1.0, end: 1.25) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: _PumpCurve()))); } @override @@ -54,25 +47,16 @@ class _SpinKitPumpingHeartState extends State @override Widget build(BuildContext context) { - return ScaleTransition( - scale: _anim1, - child: _itemBuilder(0), - ); + return ScaleTransition(scale: _animation, child: _itemBuilder(0)); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : Icon( - Icons.favorite, - color: widget.color, - size: widget.size, - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : Icon(Icons.favorite, color: widget.color, size: widget.size); } -class MyCurve extends Curve { - const MyCurve(); +class _PumpCurve extends Curve { + const _PumpCurve(); @override double transform(double t) { @@ -86,8 +70,7 @@ class MyCurve extends Curve { return pow(t - 0.5, 1.0) * 2.27272727; } else if (t >= 0.72 && t < 0.94) { return 0.5 - (pow(t - 0.72, 1.0) * 2.27272727); - } else { - return 0.0; } + return 0.0; } } diff --git a/lib/src/ring.dart b/lib/src/ring.dart index 8957ace..d1696b0 100644 --- a/lib/src/ring.dart +++ b/lib/src/ring.dart @@ -25,38 +25,23 @@ class SpinKitRing extends StatefulWidget { _SpinKitRingState createState() => _SpinKitRingState(); } -class _SpinKitRingState extends State - with SingleTickerProviderStateMixin { +class _SpinKitRingState extends State with SingleTickerProviderStateMixin { AnimationController _controller; Animation _animation1, _animation2, _animation3; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 1.0, curve: Curves.linear), - ), - )..addListener(() => setState(() {})); - - _animation2 = Tween(begin: -2 / 3, end: 1 / 2).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.5, 1.0, curve: Curves.linear), - ), - )..addListener(() => setState(() {})); - - _animation3 = Tween(begin: 0.25, end: 5 / 6).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 1.0, curve: _MyCurve()), - ), - )..addListener(() => setState(() {})); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation1 = Tween(begin: 0.0, end: 1.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: Curves.linear))); + _animation2 = Tween(begin: -2 / 3, end: 1 / 2) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.5, 1.0, curve: Curves.linear))); + _animation3 = Tween(begin: 0.25, end: 5 / 6) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: SpinKitRingCurve()))); } @override @@ -67,11 +52,9 @@ class _SpinKitRingState extends State @override Widget build(BuildContext context) { - final Matrix4 transform = Matrix4.identity() - ..rotateZ((_animation1.value) * 5 * pi / 6); return Center( child: Transform( - transform: transform, + transform: Matrix4.identity()..rotateZ((_animation1.value) * 5 * pi / 6), alignment: FractionalOffset.center, child: SizedBox.fromSize( size: Size.square(widget.size), @@ -111,36 +94,22 @@ class RingPainter extends CustomPainter { void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = (min(size.width, size.height) - paintWidth) / 2; - - final progressAngle = 2 * pi * progressPercent; - canvas.drawArc( - Rect.fromCircle( - center: center, - radius: radius, - ), + Rect.fromCircle(center: center, radius: radius), startAngle, - progressAngle, + 2 * pi * progressPercent, false, trackPaint, ); } @override - bool shouldRepaint(CustomPainter oldDelegate) { - return true; - } + bool shouldRepaint(CustomPainter oldDelegate) => true; } -class _MyCurve extends Curve { - const _MyCurve(); +class SpinKitRingCurve extends Curve { + const SpinKitRingCurve(); @override - double transform(double t) { - if (t <= 0.5) { - return 2 * t; - } else { - return 2 * (1 - t); - } - } + double transform(double t) => (t <= 0.5) ? 2 * t : 2 * (1 - t); } diff --git a/lib/src/ripple.dart b/lib/src/ripple.dart index 51c9160..faa83fd 100644 --- a/lib/src/ripple.dart +++ b/lib/src/ripple.dart @@ -1,8 +1,7 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; class SpinKitRipple extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitRipple({ + const SpinKitRipple({ Key key, this.color, this.size = 50.0, @@ -10,9 +9,7 @@ class SpinKitRipple extends StatefulWidget { this.itemBuilder, this.duration = const Duration(milliseconds: 1800), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), assert(borderWidth != null), @@ -29,31 +26,21 @@ class SpinKitRipple extends StatefulWidget { _SpinKitRippleState createState() => _SpinKitRippleState(); } -class _SpinKitRippleState extends State - with TickerProviderStateMixin { +class _SpinKitRippleState extends State with TickerProviderStateMixin { AnimationController _controller; Animation _animation1, _animation2; @override void initState() { super.initState(); - _controller = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); - - _animation1 = Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 0.75, curve: Curves.linear), - ), - )..addListener(() => setState(() {})); - _animation2 = Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.25, 1.0, curve: Curves.linear), - ), - )..addListener(() => setState(() {})); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation1 = Tween(begin: 0.0, end: 1.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 0.75, curve: Curves.linear))); + _animation2 = Tween(begin: 0.0, end: 1.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.25, 1.0, curve: Curves.linear))); } @override @@ -69,17 +56,11 @@ class _SpinKitRippleState extends State children: [ Opacity( opacity: 1.0 - _animation1.value, - child: Transform.scale( - scale: _animation1.value, - child: _itemBuilder(0), - ), + child: Transform.scale(scale: _animation1.value, child: _itemBuilder(0)), ), Opacity( opacity: 1.0 - _animation2.value, - child: Transform.scale( - scale: _animation2.value, - child: _itemBuilder(1), - ), + child: Transform.scale(scale: _animation2.value, child: _itemBuilder(1)), ), ], ), @@ -94,8 +75,7 @@ class _SpinKitRippleState extends State : DecoratedBox( decoration: BoxDecoration( shape: BoxShape.circle, - border: - Border.all(color: widget.color, width: widget.borderWidth), + border: Border.all(color: widget.color, width: widget.borderWidth), ), ), ); diff --git a/lib/src/rotating_circle.dart b/lib/src/rotating_circle.dart index f565342..0a5e113 100644 --- a/lib/src/rotating_circle.dart +++ b/lib/src/rotating_circle.dart @@ -1,17 +1,14 @@ import 'package:flutter/widgets.dart'; class SpinKitRotatingCircle extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitRotatingCircle({ + const SpinKitRotatingCircle({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -26,32 +23,21 @@ class SpinKitRotatingCircle extends StatefulWidget { _SpinKitRotatingCircleState createState() => _SpinKitRotatingCircleState(); } -class _SpinKitRotatingCircleState extends State - with SingleTickerProviderStateMixin { +class _SpinKitRotatingCircleState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _animation1; - Animation _animation2; + Animation _animation1, _animation2; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 0.5, curve: Curves.easeIn), - ), - )..addListener(() => setState(() {})); - - _animation2 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.5, 1.0, curve: Curves.easeOut), - ), - )..addListener(() => setState(() {})); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation1 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 0.5, curve: Curves.easeIn))); + _animation2 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.5, 1.0, curve: Curves.easeOut))); } @override @@ -62,29 +48,18 @@ class _SpinKitRotatingCircleState extends State @override Widget build(BuildContext context) { - final Matrix4 transform = Matrix4.identity() - ..rotateX((0 - _animation1.value) * 0.0174533) - ..rotateY((0 - _animation2.value) * 0.0174533); return Center( child: Transform( - transform: transform, + transform: Matrix4.identity() + ..rotateX((0 - _animation1.value) * 0.0174533) + ..rotateY((0 - _animation2.value) * 0.0174533), alignment: FractionalOffset.center, - child: SizedBox.fromSize( - size: Size.square(widget.size), - child: _itemBuilder(0), - ), + child: SizedBox.fromSize(size: Size.square(widget.size), child: _itemBuilder(0)), ), ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: BoxShape.circle, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: BoxShape.circle)); } diff --git a/lib/src/rotating_plain.dart b/lib/src/rotating_plain.dart index ab7b6ea..323dc3d 100644 --- a/lib/src/rotating_plain.dart +++ b/lib/src/rotating_plain.dart @@ -1,17 +1,14 @@ import 'package:flutter/widgets.dart'; class SpinKitRotatingPlain extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitRotatingPlain({ + const SpinKitRotatingPlain({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -26,32 +23,21 @@ class SpinKitRotatingPlain extends StatefulWidget { _SpinKitRotatingPlainState createState() => _SpinKitRotatingPlainState(); } -class _SpinKitRotatingPlainState extends State - with SingleTickerProviderStateMixin { +class _SpinKitRotatingPlainState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _animation1; - Animation _animation2; + Animation _animation1, _animation2; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 0.5, curve: Curves.easeIn), - ), - )..addListener(() => setState(() {})); - - _animation2 = Tween(begin: 0.0, end: 180.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.5, 1.0, curve: Curves.easeOut), - ), - )..addListener(() => setState(() {})); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation1 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 0.5, curve: Curves.easeIn))); + _animation2 = Tween(begin: 0.0, end: 180.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.5, 1.0, curve: Curves.easeOut))); } @override @@ -62,12 +48,11 @@ class _SpinKitRotatingPlainState extends State @override Widget build(BuildContext context) { - final Matrix4 transform = Matrix4.identity() - ..rotateX((0 - _animation1.value) * 0.0174533) - ..rotateY((0 - _animation2.value) * 0.0174533); return Center( child: Transform( - transform: transform, + transform: Matrix4.identity() + ..rotateX((0 - _animation1.value) * 0.0174533) + ..rotateY((0 - _animation2.value) * 0.0174533), alignment: FractionalOffset.center, child: SizedBox.fromSize( size: Size.square(widget.size), @@ -77,13 +62,7 @@ class _SpinKitRotatingPlainState extends State ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color)); } diff --git a/lib/src/spinning_circle.dart b/lib/src/spinning_circle.dart index 1a83035..c450058 100644 --- a/lib/src/spinning_circle.dart +++ b/lib/src/spinning_circle.dart @@ -3,8 +3,7 @@ import 'dart:math'; import 'package:flutter/widgets.dart'; class SpinKitSpinningCircle extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitSpinningCircle({ + const SpinKitSpinningCircle({ Key key, this.color, this.shape = BoxShape.circle, @@ -12,9 +11,7 @@ class SpinKitSpinningCircle extends StatefulWidget { this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(shape != null), assert(size != null), @@ -31,24 +28,19 @@ class SpinKitSpinningCircle extends StatefulWidget { _SpinKitSpinningCircleState createState() => _SpinKitSpinningCircleState(); } -class _SpinKitSpinningCircleState extends State - with SingleTickerProviderStateMixin { +class _SpinKitSpinningCircleState extends State with SingleTickerProviderStateMixin { AnimationController _controller; - Animation _animation1; + Animation _animation; @override void initState() { super.initState(); - _controller = widget.controller ?? - AnimationController(vsync: this, duration: widget.duration); - _animation1 = Tween(begin: 0.0, end: 7.0).animate( - CurvedAnimation( - parent: _controller, - curve: const Interval(0.0, 1.0, curve: Curves.easeOut), - ), - )..addListener(() => setState(() {})); - _controller.repeat(); + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + _animation = Tween(begin: 0.0, end: 7.0) + .animate(CurvedAnimation(parent: _controller, curve: const Interval(0.0, 1.0, curve: Curves.easeOut))); } @override @@ -59,11 +51,9 @@ class _SpinKitSpinningCircleState extends State @override Widget build(BuildContext context) { - final Matrix4 transform = Matrix4.identity() - ..rotateY((0 - _animation1.value) * pi); return Center( child: Transform( - transform: transform, + transform: Matrix4.identity()..rotateY((0 - _animation.value) * pi), alignment: FractionalOffset.center, child: SizedBox.fromSize( size: Size.square(widget.size), @@ -73,14 +63,7 @@ class _SpinKitSpinningCircleState extends State ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: widget.shape, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: widget.shape)); } diff --git a/lib/src/square_circle.dart b/lib/src/square_circle.dart new file mode 100644 index 0000000..4b4b963 --- /dev/null +++ b/lib/src/square_circle.dart @@ -0,0 +1,76 @@ +import 'dart:math' as math; + +import 'package:flutter/widgets.dart'; +import 'package:flutter_spinkit/src/utils.dart'; + +class SpinKitSquareCircle extends StatefulWidget { + const SpinKitSquareCircle({ + Key key, + this.color, + this.size = 50.0, + this.itemBuilder, + this.duration = const Duration(milliseconds: 500), + this.controller, + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), + 'You should specify either a itemBuilder or a color'), + assert(size != null), + super(key: key); + + final Color color; + final double size; + final IndexedWidgetBuilder itemBuilder; + final Duration duration; + final AnimationController controller; + + @override + _SpinKitSquareCircleState createState() => _SpinKitSquareCircleState(); +} + +class _SpinKitSquareCircleState extends State with SingleTickerProviderStateMixin { + AnimationController controller; + Animation animationCurve; + Animation animationSize; + + @override + void initState() { + super.initState(); + + controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..addStatusListener(autoReverseFn(() => controller)) + ..forward(); + final animation = CurvedAnimation(parent: controller, curve: Curves.easeInOutCubic); + animationCurve = Tween(begin: 1.0, end: 0.0).animate(animation); + animationSize = Tween(begin: 0.5, end: 1.0).animate(animation); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final sizeValue = widget.size * animationSize.value; + return Center( + child: Transform( + transform: Matrix4.identity()..rotateZ(animationCurve.value * math.pi), + alignment: FractionalOffset.center, + child: SizedBox.fromSize( + size: Size.square(sizeValue), + child: _itembuilder(0, 0.5 * sizeValue * animationCurve.value), + ), + ), + ); + } + + Widget _itembuilder(int index, double curveValue) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox( + decoration: BoxDecoration( + color: widget.color, + borderRadius: BorderRadius.all(Radius.circular(curveValue)), + ), + ); +} diff --git a/lib/src/three_bounce.dart b/lib/src/three_bounce.dart index 2a06566..94416b6 100644 --- a/lib/src/three_bounce.dart +++ b/lib/src/three_bounce.dart @@ -2,17 +2,14 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; class SpinKitThreeBounce extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitThreeBounce({ + const SpinKitThreeBounce({ Key key, this.color, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1400), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(size != null), super(key: key); @@ -27,21 +24,19 @@ class SpinKitThreeBounce extends StatefulWidget { _SpinKitThreeBounceState createState() => _SpinKitThreeBounceState(); } -class _SpinKitThreeBounceState extends State - with SingleTickerProviderStateMixin { - AnimationController _scaleCtrl; +class _SpinKitThreeBounceState extends State with SingleTickerProviderStateMixin { + AnimationController _controller; @override void initState() { super.initState(); - _scaleCtrl = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override void dispose() { - _scaleCtrl.dispose(); + _controller.dispose(); super.dispose(); } @@ -52,35 +47,18 @@ class _SpinKitThreeBounceState extends State size: Size(widget.size * 2, widget.size), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - _circle(0, .0), - _circle(1, .2), - _circle(2, .4), - ], + children: List.generate(3, (i) { + return ScaleTransition( + scale: DelayTween(begin: 0.0, end: 1.0, delay: i * .2).animate(_controller), + child: SizedBox.fromSize(size: Size.square(widget.size * 0.5), child: _itemBuilder(i)), + ); + }), ), ), ); } - Widget _circle(int index, double delay) { - final _size = widget.size * 0.5; - return ScaleTransition( - scale: DelayTween(begin: 0.0, end: 1.0, delay: delay).animate(_scaleCtrl), - child: SizedBox.fromSize( - size: Size.square(_size), - child: _itemBuilder(index), - ), - ); - } - - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: BoxShape.circle, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: BoxShape.circle)); } diff --git a/lib/src/utils.dart b/lib/src/utils.dart index acc38de..210455e 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -2,35 +2,23 @@ import 'dart:math' as math show sin, pi; import 'package:flutter/widgets.dart'; -class DelayTween extends Tween { - DelayTween({ - double begin, - double end, - this.delay, - }) : super(begin: begin, end: end); - - final double delay; - - @override - double lerp(double t) { - return super.lerp((math.sin((t - delay) * 2 * math.pi) + 1) / 2); - } - - @override - double evaluate(Animation animation) => lerp(animation.value); +Function(AnimationStatus status) autoReverseFn(AnimationController Function() controllerFactory) { + return (AnimationStatus status) { + if (status == AnimationStatus.completed) { + controllerFactory().reverse(); + } else if (status == AnimationStatus.dismissed) { + controllerFactory().forward(); + } + }; } -class AngleDelayTween extends Tween { - AngleDelayTween({ - double begin, - double end, - this.delay, - }) : super(begin: begin, end: end); +class DelayTween extends Tween { + DelayTween({double begin, double end, this.delay}) : super(begin: begin, end: end); final double delay; @override - double lerp(double t) => super.lerp(math.sin((t - delay) * math.pi * 0.5)); + double lerp(double t) => super.lerp((math.sin((t - delay) * 2 * math.pi) + 1) / 2); @override double evaluate(Animation animation) => lerp(animation.value); diff --git a/lib/src/wandering_cubes.dart b/lib/src/wandering_cubes.dart index 9e3f7ac..b560a3f 100644 --- a/lib/src/wandering_cubes.dart +++ b/lib/src/wandering_cubes.dart @@ -1,24 +1,23 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; class SpinKitWanderingCubes extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitWanderingCubes({ + const SpinKitWanderingCubes({ Key key, this.color, this.shape = BoxShape.rectangle, this.size = 50.0, this.itemBuilder, this.duration = const Duration(milliseconds: 1800), - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(shape != null), assert(size != null), + offset = size * 0.75, super(key: key); final Color color; final BoxShape shape; + final double offset; final double size; final IndexedWidgetBuilder itemBuilder; final Duration duration; @@ -27,97 +26,43 @@ class SpinKitWanderingCubes extends StatefulWidget { _SpinKitWanderingCubesState createState() => _SpinKitWanderingCubesState(); } -class _SpinKitWanderingCubesState extends State - with TickerProviderStateMixin { +class _SpinKitWanderingCubesState extends State with TickerProviderStateMixin { AnimationController _scaleCtrl, _rotateCtrl, _translateCtrl; Animation _scale1, _scale2, _scale3, _scale4, _rotate; Animation _translate1, _translate2, _translate3, _translate4; - double _offset; - - void initTranslateAnim() { - _translateCtrl = - AnimationController(vsync: this, duration: widget.duration); - - _translate1 = Tween(begin: 0.0, end: _offset).animate( - CurvedAnimation( - parent: _translateCtrl, - curve: const Interval(0.0, 0.25, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _translate2 = Tween(begin: 0.0, end: _offset).animate( - CurvedAnimation( - parent: _translateCtrl, - curve: const Interval(0.25, 0.5, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _translate3 = Tween(begin: 0.0, end: -_offset).animate( - CurvedAnimation( - parent: _translateCtrl, - curve: const Interval(0.5, 0.75, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _translate4 = Tween(begin: 0.0, end: -_offset).animate( - CurvedAnimation( - parent: _translateCtrl, - curve: const Interval(0.75, 1.0, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _translateCtrl.repeat(); - } - - void initScaleAnim() { - _scaleCtrl = AnimationController(vsync: this, duration: widget.duration); - - _scale1 = Tween(begin: 1.0, end: 0.5).animate( - CurvedAnimation( - parent: _scaleCtrl, - curve: const Interval(0.0, 0.25, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _scale2 = Tween(begin: 1.0, end: 2.0).animate( - CurvedAnimation( - parent: _scaleCtrl, - curve: const Interval(0.25, 0.5, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _scale3 = Tween(begin: 1.0, end: 0.5).animate( - CurvedAnimation( - parent: _scaleCtrl, - curve: const Interval(0.5, 0.75, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _scale4 = Tween(begin: 1.0, end: 2.0).animate( - CurvedAnimation( - parent: _scaleCtrl, - curve: const Interval(0.75, 1.0, curve: Curves.easeInOut), - ), - )..addListener(() => setState(() {})); - - _scaleCtrl.repeat(); - } @override void initState() { super.initState(); - _offset = widget.size * 0.75; - - initTranslateAnim(); - initScaleAnim(); - - _rotateCtrl = AnimationController(vsync: this, duration: widget.duration); - - _rotate = Tween(begin: 0.0, end: 360.0).animate( - CurvedAnimation(parent: _translateCtrl, curve: Curves.linear), - )..addListener(() => setState(() {})); - _rotateCtrl.repeat(); + _translateCtrl = AnimationController(vsync: this, duration: widget.duration) + ..addListener(() => setState(() {})) + ..repeat(); + _translate1 = Tween(begin: 0.0, end: widget.offset) + .animate(CurvedAnimation(parent: _translateCtrl, curve: const Interval(0.0, 0.25, curve: Curves.easeInOut))); + _translate2 = Tween(begin: 0.0, end: widget.offset) + .animate(CurvedAnimation(parent: _translateCtrl, curve: const Interval(0.25, 0.5, curve: Curves.easeInOut))); + _translate3 = Tween(begin: 0.0, end: -widget.offset) + .animate(CurvedAnimation(parent: _translateCtrl, curve: const Interval(0.5, 0.75, curve: Curves.easeInOut))); + _translate4 = Tween(begin: 0.0, end: -widget.offset) + .animate(CurvedAnimation(parent: _translateCtrl, curve: const Interval(0.75, 1.0, curve: Curves.easeInOut))); + + _scaleCtrl = AnimationController(vsync: this, duration: widget.duration) + ..addListener(() => setState(() {})) + ..repeat(); + _scale1 = Tween(begin: 1.0, end: 0.5) + .animate(CurvedAnimation(parent: _scaleCtrl, curve: const Interval(0.0, 0.25, curve: Curves.easeInOut))); + _scale2 = Tween(begin: 1.0, end: 2.0) + .animate(CurvedAnimation(parent: _scaleCtrl, curve: const Interval(0.25, 0.5, curve: Curves.easeInOut))); + _scale3 = Tween(begin: 1.0, end: 0.5) + .animate(CurvedAnimation(parent: _scaleCtrl, curve: const Interval(0.5, 0.75, curve: Curves.easeInOut))); + _scale4 = Tween(begin: 1.0, end: 2.0) + .animate(CurvedAnimation(parent: _scaleCtrl, curve: const Interval(0.75, 1.0, curve: Curves.easeInOut))); + + _rotateCtrl = AnimationController(vsync: this, duration: widget.duration) + ..addListener(() => setState(() {})) + ..repeat(); + _rotate = Tween(begin: 0.0, end: 360.0).animate(CurvedAnimation(parent: _translateCtrl, curve: Curves.linear)); } @override @@ -144,13 +89,6 @@ class _SpinKitWanderingCubesState extends State } Widget _cube(int index, [bool offset = false]) { - final _size = widget.size * 0.25; - final Matrix4 _tScale = Matrix4.identity() - ..scale(_scale2.value) - ..scale(_scale3.value) - ..scale(_scale4.value) - ..scale(_scale1.value); - Matrix4 _tTranslate; if (offset == true) { _tTranslate = Matrix4.identity() @@ -168,15 +106,19 @@ class _SpinKitWanderingCubesState extends State return Positioned( top: 0.0, - left: offset == true ? 0.0 : _offset, + left: offset == true ? 0.0 : widget.offset, child: Transform( transform: _tTranslate, child: Transform.rotate( angle: _rotate.value * 0.0174533, child: Transform( - transform: _tScale, + transform: Matrix4.identity() + ..scale(_scale2.value) + ..scale(_scale3.value) + ..scale(_scale4.value) + ..scale(_scale1.value), child: SizedBox.fromSize( - size: Size.square(_size), + size: Size.square(widget.size * 0.25), child: _itemBuilder(index), ), ), @@ -185,14 +127,7 @@ class _SpinKitWanderingCubesState extends State ); } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - shape: widget.shape, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color, shape: widget.shape)); } diff --git a/lib/src/wave.dart b/lib/src/wave.dart index 6b9a44f..044883f 100644 --- a/lib/src/wave.dart +++ b/lib/src/wave.dart @@ -1,11 +1,10 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_spinkit/src/utils.dart'; enum SpinKitWaveType { start, end, center } class SpinKitWave extends StatefulWidget { - // ignore: prefer_const_constructors_in_immutables - SpinKitWave({ + const SpinKitWave({ Key key, this.color, this.type = SpinKitWaveType.start, @@ -13,9 +12,7 @@ class SpinKitWave extends StatefulWidget { this.itemBuilder, this.duration = const Duration(milliseconds: 1200), this.controller, - }) : assert( - !(itemBuilder is IndexedWidgetBuilder && color is Color) && - !(itemBuilder == null && color == null), + }) : assert(!(itemBuilder is IndexedWidgetBuilder && color is Color) && !(itemBuilder == null && color == null), 'You should specify either a itemBuilder or a color'), assert(type != null), assert(size != null), @@ -32,87 +29,56 @@ class SpinKitWave extends StatefulWidget { _SpinKitWaveState createState() => _SpinKitWaveState(); } -class _SpinKitWaveState extends State - with SingleTickerProviderStateMixin { - AnimationController _scaleCtrl; +class _SpinKitWaveState extends State with SingleTickerProviderStateMixin { + AnimationController _controller; @override void initState() { super.initState(); - _scaleCtrl = (widget.controller ?? - AnimationController(vsync: this, duration: widget.duration)) - ..repeat(); + + _controller = (widget.controller ?? AnimationController(vsync: this, duration: widget.duration))..repeat(); } @override void dispose() { - _scaleCtrl.dispose(); + _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - List _bars; - if (widget.type == SpinKitWaveType.start) { - _bars = [ - _bar(0, -1.2), - _bar(1, -1.1), - _bar(2, -1.0), - _bar(3, -.9), - _bar(4, -.8), - ]; - } else if (widget.type == SpinKitWaveType.end) { - _bars = [ - _bar(0, -.8), - _bar(1, -.9), - _bar(2, -1.0), - _bar(3, -1.1), - _bar(4, -1.2), - ]; - } else if (widget.type == SpinKitWaveType.center) { - _bars = [ - _bar(0, -0.75), - _bar(1, -0.95), - _bar(2, -1.2), - _bar(3, -0.95), - _bar(4, -0.75), - ]; - } + final List _bars = getAnimationDelay(); return Center( child: SizedBox.fromSize( size: Size(widget.size * 1.25, widget.size), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _bars, + children: List.generate(_bars.length, (i) { + return ScaleYWidget( + scaleY: DelayTween(begin: .4, end: 1.0, delay: _bars[i]).animate(_controller), + child: SizedBox.fromSize(size: Size(widget.size * 0.2, widget.size), child: _itemBuilder(i)), + ); + }), ), ), ); } - Widget _bar(int index, double delay) { - final _size = widget.size * 0.2; - return ScaleYWidget( - scaleY: DelayTween( - begin: .4, - end: 1.0, - delay: delay, - ).animate(_scaleCtrl), - child: SizedBox.fromSize( - size: Size(_size, widget.size), - child: _itemBuilder(index), - ), - ); + List getAnimationDelay() { + switch (widget.type) { + case SpinKitWaveType.start: + return [-1.2, -1.1, -1.0, -.9, -.8]; + case SpinKitWaveType.end: + return [-.8, -.9, -1.0, -1.1, -1.2]; + case SpinKitWaveType.center: + default: + return [-0.75, -0.95, -1.2, -0.95, -0.75]; + } } - Widget _itemBuilder(int index) { - return widget.itemBuilder != null - ? widget.itemBuilder(context, index) - : DecoratedBox( - decoration: BoxDecoration( - color: widget.color, - ), - ); - } + Widget _itemBuilder(int index) => widget.itemBuilder != null + ? widget.itemBuilder(context, index) + : DecoratedBox(decoration: BoxDecoration(color: widget.color)); } class ScaleYWidget extends AnimatedWidget { @@ -126,16 +92,10 @@ class ScaleYWidget extends AnimatedWidget { final Widget child; final Alignment alignment; - Animation get scaleY => listenable; + Animation get scale => listenable; @override Widget build(BuildContext context) { - final double scaleValue = scaleY.value; - final Matrix4 transform = Matrix4.identity()..scale(1.0, scaleValue, 1.0); - return Transform( - transform: transform, - alignment: alignment, - child: child, - ); + return Transform(transform: Matrix4.identity()..scale(1.0, scale.value, 1.0), alignment: alignment, child: child); } } diff --git a/makefile b/makefile new file mode 100644 index 0000000..96d776f --- /dev/null +++ b/makefile @@ -0,0 +1,8 @@ +test_coverage: + flutter test --no-pub --coverage + +build_coverage: + make test_coverage && genhtml -o coverage coverage/lcov.info + +open_coverage: + make build_coverage && open coverage/index.html \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 90f1b9b..2a9be7e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,20 +1,34 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.2.0" + version: "2.3.0" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" charcode: dependency: transitive description: @@ -29,6 +43,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.14.11" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" flutter: dependency: "direct main" description: flutter @@ -39,6 +67,13 @@ packages: description: flutter source: sdk version: "0.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.4" matcher: dependency: transitive description: @@ -52,28 +87,35 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.1.7" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" + version: "1.6.4" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0+1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" quiver: dependency: transitive description: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.3" + version: "2.0.5" sky_engine: dependency: transitive description: flutter @@ -106,7 +148,7 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" term_glyph: dependency: transitive description: @@ -135,6 +177,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.8" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "3.5.0" sdks: - dart: ">=2.2.2 <3.0.0" + dart: ">=2.5.0 <3.0.0" flutter: ">=0.1.4 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8f467a2..8c3f934 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_spinkit description: A collection of loading indicators animated with flutter. Heavily inspired by @tobiasahlin's SpinKit. -version: 4.0.0 +version: 4.1.0 homepage: https://github.com/jogboms/flutter_spinkit authors: @@ -8,7 +8,7 @@ authors: - Ayush Agarwal environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.5.0 <3.0.0" flutter: ">=0.1.4 <2.0.0" dependencies: diff --git a/screenshots/square_circle.gif b/screenshots/square_circle.gif new file mode 100644 index 0000000..42e3fde Binary files /dev/null and b/screenshots/square_circle.gif differ diff --git a/test/chasing_dots_test.dart b/test/chasing_dots_test.dart new file mode 100644 index 0000000..d803f8e --- /dev/null +++ b/test/chasing_dots_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("ChasingDots", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitChasingDots(), throwsAssertionError); + expect(() => SpinKitChasingDots(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitChasingDots(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitChasingDots(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitChasingDots(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitChasingDots(color: Colors.white))); + expect(find.byType(SpinKitChasingDots), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitChasingDots(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitChasingDots), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitChasingDots(color: Colors.white))); + expect(find.byType(SpinKitChasingDots), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/circle_test.dart b/test/circle_test.dart new file mode 100644 index 0000000..7796ff8 --- /dev/null +++ b/test/circle_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("Circle", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitCircle(), throwsAssertionError); + expect(() => SpinKitCircle(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitCircle(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitCircle(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitCircle(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitCircle(color: Colors.white))); + expect(find.byType(SpinKitCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitCircle(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitCircle), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitCircle(color: Colors.white))); + expect(find.byType(SpinKitCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/cube_grid_test.dart b/test/cube_grid_test.dart new file mode 100644 index 0000000..0e679a1 --- /dev/null +++ b/test/cube_grid_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("CubeGrid", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitCubeGrid(), throwsAssertionError); + expect(() => SpinKitCubeGrid(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitCubeGrid(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitCubeGrid(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitCubeGrid(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitCubeGrid(color: Colors.white))); + expect(find.byType(SpinKitCubeGrid), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitCubeGrid(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitCubeGrid), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitCubeGrid(color: Colors.white))); + expect(find.byType(SpinKitCubeGrid), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/double_bounce_test.dart b/test/double_bounce_test.dart new file mode 100644 index 0000000..8e44e67 --- /dev/null +++ b/test/double_bounce_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("DoubleBounce", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitDoubleBounce(), throwsAssertionError); + expect(() => SpinKitDoubleBounce(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitDoubleBounce(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitDoubleBounce(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitDoubleBounce(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitDoubleBounce(color: Colors.white))); + expect(find.byType(SpinKitDoubleBounce), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitDoubleBounce(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitDoubleBounce), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitDoubleBounce(color: Colors.white))); + expect(find.byType(SpinKitDoubleBounce), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/dual_ring_test.dart b/test/dual_ring_test.dart new file mode 100644 index 0000000..8af330b --- /dev/null +++ b/test/dual_ring_test.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("DualRing", () { + testWidgets('needs a non-null color', (WidgetTester tester) async { + expect(() => SpinKitDualRing(color: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitDualRing(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitDualRing(color: Colors.white))); + expect(find.byType(SpinKitDualRing), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitDualRing(color: Colors.white))); + expect(find.byType(SpinKitDualRing), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/fading_circle_test.dart b/test/fading_circle_test.dart new file mode 100644 index 0000000..67f3dd1 --- /dev/null +++ b/test/fading_circle_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("FadingCircle", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitFadingCircle(), throwsAssertionError); + expect(() => SpinKitFadingCircle(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingCircle(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingCircle(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingCircle(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingCircle(color: Colors.white))); + expect(find.byType(SpinKitFadingCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingCircle(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitFadingCircle), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitFadingCircle(color: Colors.white))); + expect(find.byType(SpinKitFadingCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/fading_cube_test.dart b/test/fading_cube_test.dart new file mode 100644 index 0000000..50cf7a2 --- /dev/null +++ b/test/fading_cube_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("FadingCube", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitFadingCube(), throwsAssertionError); + expect(() => SpinKitFadingCube(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingCube(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingCube(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingCube(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingCube(color: Colors.white))); + expect(find.byType(SpinKitFadingCube), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingCube(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitFadingCube), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitFadingCube(color: Colors.white))); + expect(find.byType(SpinKitFadingCube), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/fading_four_test.dart b/test/fading_four_test.dart new file mode 100644 index 0000000..18eedeb --- /dev/null +++ b/test/fading_four_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("FadingFour", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitFadingFour(), throwsAssertionError); + expect(() => SpinKitFadingFour(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingFour(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingFour(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingFour(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs shape to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingFour(color: Colors.white, shape: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingFour(color: Colors.white))); + expect(find.byType(SpinKitFadingFour), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingFour(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitFadingFour), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitFadingFour(color: Colors.white))); + expect(find.byType(SpinKitFadingFour), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/fading_grid_test.dart b/test/fading_grid_test.dart new file mode 100644 index 0000000..d27ed3c --- /dev/null +++ b/test/fading_grid_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("FadingGrid", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitFadingGrid(), throwsAssertionError); + expect(() => SpinKitFadingGrid(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingGrid(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingGrid(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingGrid(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs shape to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFadingGrid(color: Colors.white, shape: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingGrid(color: Colors.white))); + expect(find.byType(SpinKitFadingGrid), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFadingGrid(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitFadingGrid), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitFadingGrid(color: Colors.white))); + expect(find.byType(SpinKitFadingGrid), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/flutter_spinkit_test.dart b/test/flutter_spinkit_test.dart deleted file mode 100644 index ab73b3a..0000000 --- a/test/flutter_spinkit_test.dart +++ /dev/null @@ -1 +0,0 @@ -void main() {} diff --git a/test/folding_cube_test.dart b/test/folding_cube_test.dart new file mode 100644 index 0000000..54f8633 --- /dev/null +++ b/test/folding_cube_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("FoldingCube", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitFoldingCube(), throwsAssertionError); + expect(() => SpinKitFoldingCube(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFoldingCube(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFoldingCube(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitFoldingCube(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFoldingCube(color: Colors.white))); + expect(find.byType(SpinKitFoldingCube), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitFoldingCube(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitFoldingCube), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitFoldingCube(color: Colors.white))); + expect(find.byType(SpinKitFoldingCube), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/helpers.dart b/test/helpers.dart new file mode 100644 index 0000000..150a434 --- /dev/null +++ b/test/helpers.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class FakeBox extends SizedBox {} + +final fakeBoxBuilder = (BuildContext _, int index) => FakeBox(); + +Widget createWidgetsApp(Widget widget) { + return WidgetsApp( + color: Colors.grey[900], + home: Center(child: widget), + pageRouteBuilder: (settings, builder) => MaterialPageRoute(settings: settings, builder: builder), + ); +} + +Widget createMaterialApp(Widget widget) { + return MaterialApp(theme: ThemeData.dark(), home: Center(child: widget)); +} diff --git a/test/hour_glass_test.dart b/test/hour_glass_test.dart new file mode 100644 index 0000000..e6e1e73 --- /dev/null +++ b/test/hour_glass_test.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("HourGlass", () { + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitHourGlass(color: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitHourGlass(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitHourGlass(color: Colors.white))); + expect(find.byType(SpinKitHourGlass), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitHourGlass(color: Colors.white))); + expect(find.byType(SpinKitHourGlass), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/pouring_hour_glass_test.dart b/test/pouring_hour_glass_test.dart new file mode 100644 index 0000000..6fc57c2 --- /dev/null +++ b/test/pouring_hour_glass_test.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("PouringHourglass", () { + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPouringHourglass(color: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPouringHourglass(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitPouringHourglass(color: Colors.white))); + expect(find.byType(SpinKitPouringHourglass), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitPouringHourglass(color: Colors.white))); + expect(find.byType(SpinKitPouringHourglass), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/pulse_test.dart b/test/pulse_test.dart new file mode 100644 index 0000000..5fb36f7 --- /dev/null +++ b/test/pulse_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("Pulse", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitPulse(), throwsAssertionError); + expect(() => SpinKitPulse(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPulse(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPulse(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPulse(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitPulse(color: Colors.white))); + expect(find.byType(SpinKitPulse), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitPulse(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitPulse), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitPulse(color: Colors.white))); + expect(find.byType(SpinKitPulse), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/pumping_heart_test.dart b/test/pumping_heart_test.dart new file mode 100644 index 0000000..91b8db7 --- /dev/null +++ b/test/pumping_heart_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("PumpingHeart", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitPumpingHeart(), throwsAssertionError); + expect(() => SpinKitPumpingHeart(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPumpingHeart(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPumpingHeart(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitPumpingHeart(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitPumpingHeart(color: Colors.white))); + expect(find.byType(SpinKitPumpingHeart), findsOneWidget); + expect(find.byType(Icon), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitPumpingHeart(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitPumpingHeart), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitPumpingHeart(color: Colors.white))); + expect(find.byType(SpinKitPumpingHeart), findsOneWidget); + expect(find.byType(Icon), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/ring_test.dart b/test/ring_test.dart new file mode 100644 index 0000000..e3614af --- /dev/null +++ b/test/ring_test.dart @@ -0,0 +1,45 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("Ring", () { + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRing(color: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRing(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs lineWidth to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRing(color: Colors.white, lineWidth: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRing(color: Colors.white))); + expect(find.byType(SpinKitRing), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitRing(color: Colors.white))); + expect(find.byType(SpinKitRing), findsOneWidget); + expect(find.byType(CustomPaint), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + test("on curve", () { + final curve = SpinKitRingCurve(); + expect(curve.transform(1), 0); + expect(curve.transform(.9), closeTo(.2, precisionErrorTolerance)); + expect(curve.transform(.5), 1); + expect(curve.transform(.1), closeTo(.2, precisionErrorTolerance)); + expect(curve.transform(0), 0); + }); + }); +} diff --git a/test/ripple_test.dart b/test/ripple_test.dart new file mode 100644 index 0000000..26de0b2 --- /dev/null +++ b/test/ripple_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("Ripple", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitRipple(), throwsAssertionError); + expect(() => SpinKitRipple(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRipple(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRipple(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRipple(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs borderWidth to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRipple(color: Colors.white, borderWidth: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRipple(color: Colors.white))); + expect(find.byType(SpinKitRipple), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRipple(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitRipple), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitRipple(color: Colors.white))); + expect(find.byType(SpinKitRipple), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/rotating_circle_test.dart b/test/rotating_circle_test.dart new file mode 100644 index 0000000..ef34a87 --- /dev/null +++ b/test/rotating_circle_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("RotatingCircle", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitRotatingCircle(), throwsAssertionError); + expect(() => SpinKitRotatingCircle(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRotatingCircle(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRotatingCircle(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRotatingCircle(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRotatingCircle(color: Colors.white))); + expect(find.byType(SpinKitRotatingCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRotatingCircle(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitRotatingCircle), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitRotatingCircle(color: Colors.white))); + expect(find.byType(SpinKitRotatingCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/rotating_plain_test.dart b/test/rotating_plain_test.dart new file mode 100644 index 0000000..8ba6a10 --- /dev/null +++ b/test/rotating_plain_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("RotatingPlain", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitRotatingPlain(), throwsAssertionError); + expect(() => SpinKitRotatingPlain(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRotatingPlain(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRotatingPlain(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitRotatingPlain(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRotatingPlain(color: Colors.white))); + expect(find.byType(SpinKitRotatingPlain), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitRotatingPlain(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitRotatingPlain), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitRotatingPlain(color: Colors.white))); + expect(find.byType(SpinKitRotatingPlain), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/smoke_test.dart b/test/smoke_test.dart new file mode 100644 index 0000000..076d9b0 --- /dev/null +++ b/test/smoke_test.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Smoke test', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + theme: ThemeData.dark(), + home: SingleChildScrollView( + child: Column( + children: const [ + SpinKitChasingDots(color: Colors.white), + SpinKitCircle(color: Colors.white), + SpinKitSquareCircle(color: Colors.white), + SpinKitDoubleBounce(color: Colors.white), + SpinKitCubeGrid(color: Colors.white), + SpinKitDoubleBounce(color: Colors.white), + SpinKitDualRing(color: Colors.white), + SpinKitFadingCircle(color: Colors.white), + SpinKitFadingCube(color: Colors.white), + SpinKitFadingFour(color: Colors.white), + SpinKitFadingGrid(color: Colors.white), + SpinKitFoldingCube(color: Colors.white), + SpinKitHourGlass(color: Colors.white), + SpinKitPouringHourglass(color: Colors.white), + SpinKitPulse(color: Colors.white), + SpinKitPumpingHeart(color: Colors.white), + SpinKitRing(color: Colors.white), + SpinKitRipple(color: Colors.white), + SpinKitRotatingCircle(color: Colors.white), + SpinKitRotatingPlain(color: Colors.white), + SpinKitSpinningCircle(color: Colors.white), + SpinKitThreeBounce(color: Colors.white), + SpinKitWanderingCubes(color: Colors.white), + SpinKitWave(color: Colors.white), + ], + ), + ), + )); + + await tester.pump(); + }); +} diff --git a/test/spinning_circle_test.dart b/test/spinning_circle_test.dart new file mode 100644 index 0000000..bc85200 --- /dev/null +++ b/test/spinning_circle_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("SpinningCircle", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitSpinningCircle(), throwsAssertionError); + expect(() => SpinKitSpinningCircle(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSpinningCircle(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSpinningCircle(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSpinningCircle(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs shape to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSpinningCircle(color: Colors.white, shape: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitSpinningCircle(color: Colors.white))); + expect(find.byType(SpinKitSpinningCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitSpinningCircle(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitSpinningCircle), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitSpinningCircle(color: Colors.white))); + expect(find.byType(SpinKitSpinningCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/square_circle_test.dart b/test/square_circle_test.dart new file mode 100644 index 0000000..ecf094c --- /dev/null +++ b/test/square_circle_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("SquareCircle", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitSquareCircle(), throwsAssertionError); + expect(() => SpinKitSquareCircle(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSquareCircle(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSquareCircle(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitSquareCircle(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitSquareCircle(color: Colors.white))); + expect(find.byType(SpinKitSquareCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitSquareCircle(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitSquareCircle), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitSquareCircle(color: Colors.white))); + expect(find.byType(SpinKitSquareCircle), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/three_bounce_test.dart b/test/three_bounce_test.dart new file mode 100644 index 0000000..15f1a12 --- /dev/null +++ b/test/three_bounce_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("ThreeBounce", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitThreeBounce(), throwsAssertionError); + expect(() => SpinKitThreeBounce(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitThreeBounce(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitThreeBounce(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitThreeBounce(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitThreeBounce(color: Colors.white))); + expect(find.byType(SpinKitThreeBounce), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitThreeBounce(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitThreeBounce), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitThreeBounce(color: Colors.white))); + expect(find.byType(SpinKitThreeBounce), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/utils_test.dart b/test/utils_test.dart new file mode 100644 index 0000000..4d94731 --- /dev/null +++ b/test/utils_test.dart @@ -0,0 +1,67 @@ +import 'dart:ui' as ui; + +import 'package:flutter/animation.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_spinkit/src/utils.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void tick(Duration duration) { + // We don't bother running microtasks between these two calls + // because we don't use Futures in these tests and so don't care. + SchedulerBinding.instance.handleBeginFrame(duration); + SchedulerBinding.instance.handleDrawFrame(); +} + +void main() { + group("Utils", () { + group("on autoReverse", () { + setUp(() { + WidgetsFlutterBinding.ensureInitialized(); + WidgetsBinding.instance.resetEpoch(); + ui.window.onBeginFrame = null; + ui.window.onDrawFrame = null; + }); + test("works as expected", () { + final controller = AnimationController(duration: const Duration(milliseconds: 20), vsync: const TestVSync()); + final animation = CurvedAnimation(parent: controller, curve: Curves.linear); + autoReverseFn(() => controller)(AnimationStatus.dismissed); + tick(const Duration(milliseconds: 0)); + tick(const Duration(milliseconds: 10)); + tick(const Duration(milliseconds: 20)); + expect(animation.value, 1.0); + autoReverseFn(() => controller)(AnimationStatus.completed); + tick(const Duration(milliseconds: 30)); + tick(const Duration(milliseconds: 40)); + tick(const Duration(milliseconds: 50)); + expect(animation.value, 0.0); + autoReverseFn(() => controller)(AnimationStatus.dismissed); + tick(const Duration(milliseconds: 60)); + tick(const Duration(milliseconds: 70)); + tick(const Duration(milliseconds: 80)); + expect(animation.value, 1.0); + controller.stop(); + }); + + test('works with listener', () { + final log = []; + AnimationController controller; + final listener = (AnimationStatus status) { + log.add(status.index); + autoReverseFn(() => controller)(status); + }; + controller = AnimationController(duration: const Duration(milliseconds: 20), vsync: const TestVSync()) + ..addStatusListener(listener) + ..forward(); + tick(const Duration(milliseconds: 20)); + expect(log.length, 1); + tick(const Duration(milliseconds: 30)); + tick(const Duration(milliseconds: 40)); + tick(const Duration(milliseconds: 50)); + expect(log.length, 3); + controller.removeStatusListener(listener); + controller.stop(); + }); + }); + }); +} diff --git a/test/wandering_cubes_test.dart b/test/wandering_cubes_test.dart new file mode 100644 index 0000000..40feee0 --- /dev/null +++ b/test/wandering_cubes_test.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("WanderingCubes", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitWanderingCubes(), throwsAssertionError); + expect(() => SpinKitWanderingCubes(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWanderingCubes(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWanderingCubes(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWanderingCubes(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs shape to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWanderingCubes(color: Colors.white, shape: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWanderingCubes(color: Colors.white))); + expect(find.byType(SpinKitWanderingCubes), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWanderingCubes(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitWanderingCubes), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitWanderingCubes(color: Colors.white))); + expect(find.byType(SpinKitWanderingCubes), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +} diff --git a/test/wave_test.dart b/test/wave_test.dart new file mode 100644 index 0000000..5393c5c --- /dev/null +++ b/test/wave_test.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'helpers.dart'; + +void main() { + group("Wave", () { + testWidgets('needs either color or itemBuilder', (WidgetTester tester) async { + expect(() => SpinKitWave(), throwsAssertionError); + expect(() => SpinKitWave(color: Colors.white, itemBuilder: fakeBoxBuilder), throwsAssertionError); + }); + + testWidgets('needs color to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWave(color: null), throwsAssertionError); + }); + + testWidgets('needs itemBuilder to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWave(itemBuilder: null), throwsAssertionError); + }); + + testWidgets('needs size to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWave(color: Colors.white, size: null), throwsAssertionError); + }); + + testWidgets('needs type to be non-null', (WidgetTester tester) async { + expect(() => SpinKitWave(color: Colors.white, type: null), throwsAssertionError); + }); + + testWidgets('works with color', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWave(color: Colors.white))); + expect(find.byType(SpinKitWave), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('works with itemBuilder', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWave(itemBuilder: fakeBoxBuilder))); + expect(find.byType(SpinKitWave), findsOneWidget); + expect(find.byType(FakeBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + group('works with types', () { + testWidgets('on center', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWave(color: Colors.white, type: SpinKitWaveType.center))); + expect(find.byType(SpinKitWave), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('on start', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWave(color: Colors.white, type: SpinKitWaveType.start))); + expect(find.byType(SpinKitWave), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + + testWidgets('on end', (WidgetTester tester) async { + await tester.pumpWidget(createMaterialApp(SpinKitWave(color: Colors.white, type: SpinKitWaveType.end))); + expect(find.byType(SpinKitWave), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); + + testWidgets('works without Material', (WidgetTester tester) async { + await tester.pumpWidget(createWidgetsApp(SpinKitWave(color: Colors.white))); + expect(find.byType(SpinKitWave), findsOneWidget); + expect(find.byType(DecoratedBox), findsWidgets); + tester.verifyTickersWereDisposed(); + }); + }); +}