From 4024a29c9b93cfaec5ddde75bdb0a4e32fc394d6 Mon Sep 17 00:00:00 2001 From: Anthony Whitford Date: Sun, 24 May 2020 10:19:11 -0700 Subject: [PATCH 1/4] Code Review - Removed obsolete `new` keywords. - Added types to collection and function variables. - Added `final` and `const` keywords. - Replaced `null` guards with concise `?.` and `??` operators. - Added missing null check on `dispose` for `FadeAnimatedTextKit`. - In `fade.dart`, renamed the `_RotatingTextState` class to `_FadeTextState` to be consistent with the overall pattern and avoid confusion with `_RotatingTextState` in `rotate.dart`. **Warning**: - Removed `onNextBeforePause` from `ColorizeAnimatedTextKit` because it was not referenced. --- example/lib/main.dart | 12 ++--- lib/src/colorize.dart | 52 ++++++++-------------- lib/src/fade.dart | 75 ++++++++++++-------------------- lib/src/rotate.dart | 70 +++++++++++------------------ lib/src/scale.dart | 69 +++++++++++------------------ lib/src/text_liquid_fill.dart | 6 +-- lib/src/typer.dart | 65 ++++++++++----------------- lib/src/typewriter.dart | 55 ++++++++--------------- test/animated_text_kit_test.dart | 2 +- 9 files changed, 146 insertions(+), 260 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index f37d0b2..1be8abd 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:animated_text_kit/animated_text_kit.dart'; -void main() => runApp(new MyApp()); +void main() => runApp(MyApp()); const List labels = [ "Rotate", @@ -17,18 +17,18 @@ class MyApp extends StatefulWidget { /// This widget is the root of your application. @override MyAppState createState() { - return new MyAppState(); + return MyAppState(); } } class MyAppState extends State { @override Widget build(BuildContext context) { - return new MaterialApp( + return MaterialApp( title: 'Animated Text Kit', debugShowCheckedModeBanner: false, theme: ThemeData.dark(), - home: new MyHomePage(title: 'Animated Text Kit'), + home: MyHomePage(title: 'Animated Text Kit'), ); } } @@ -42,7 +42,7 @@ class MyHomePage extends StatefulWidget { }) : super(key: key); @override - _MyHomePageState createState() => new _MyHomePageState(); + _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { @@ -168,7 +168,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { - return new Scaffold( + return Scaffold( body: Column( children: [ SizedBox( diff --git a/lib/src/colorize.dart b/lib/src/colorize.dart index 4ed0cdf..e0938ac 100644 --- a/lib/src/colorize.dart +++ b/lib/src/colorize.dart @@ -3,7 +3,7 @@ import 'dart:async'; class ColorizeAnimatedTextKit extends StatefulWidget { /// List of [String] that would be displayed subsequently in the animation. - final List text; + final List text; /// Gives [TextStyle] to the text strings. final TextStyle textStyle; @@ -29,12 +29,7 @@ class ColorizeAnimatedTextKit extends StatefulWidget { /// Adds the onNext [VoidCallback] to the animated widget. /// /// Will be called right before the next text, after the pause parameter - final Function onNext; - - /// Adds the onNextBeforePause [VoidCallback] to the animated widget. - /// - /// Will be called at the end of n-1 animation, before the pause parameter - final Function onNextBeforePause; + final void Function(int, bool) onNext; /// Adds [AlignmentGeometry] property to the text in the widget. /// @@ -76,7 +71,6 @@ class ColorizeAnimatedTextKit extends StatefulWidget { this.pause, this.onTap, this.onNext, - this.onNextBeforePause, this.onFinished, this.alignment = AlignmentDirectional.topStart, this.textAlign = TextAlign.start, @@ -86,7 +80,7 @@ class ColorizeAnimatedTextKit extends StatefulWidget { : super(key: key); @override - _RotatingTextState createState() => new _RotatingTextState(); + _RotatingTextState createState() => _RotatingTextState(); } class _RotatingTextState extends State @@ -111,30 +105,16 @@ class _RotatingTextState extends State void initState() { super.initState(); - _speed = widget.speed ?? Duration(milliseconds: 200); - _pause = widget.pause ?? Duration(milliseconds: 1000); + _speed = widget.speed ?? const Duration(milliseconds: 200); + _pause = widget.pause ?? const Duration(milliseconds: 1000); _index = -1; _currentRepeatCount = 0; - for (int i = 0; i < widget.text.length; i++) { - try { - if (!widget.text[i].containsKey('text')) throw new Error(); - - _texts.add({ - 'text': widget.text[i]['text'], - 'speed': widget.text[i].containsKey('speed') - ? widget.text[i]['speed'] - : _speed, - 'pause': widget.text[i].containsKey('pause') - ? widget.text[i]['pause'] - : _pause, - }); - } catch (e) { - _texts.add({'text': widget.text[i], 'speed': _speed, 'pause': _pause}); - } - } + widget.text.forEach((text) { + _texts.add({'text': text, 'speed': _speed, 'pause': _pause}); + }); _nextAnimation(); } @@ -179,13 +159,13 @@ class _RotatingTextState extends State } void _nextAnimation() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = false; // Handling onNext callback if (_index > -1) { - if (widget.onNext != null) widget.onNext(_index, isLast); + widget.onNext?.call(_index, isLast); } if (isLast) { @@ -197,7 +177,7 @@ class _RotatingTextState extends State _currentRepeatCount++; } } else { - if (widget.onFinished != null) widget.onFinished(); + widget.onFinished?.call(); return; } } else { @@ -206,7 +186,7 @@ class _RotatingTextState extends State if (mounted) setState(() {}); - _controller = new AnimationController( + _controller = AnimationController( duration: _texts[_index]['speed'] * _texts[_index]['text'].length, vsync: this, ); @@ -217,16 +197,18 @@ class _RotatingTextState extends State (_texts[_index]['text'].length / 15.0); _fadeIn = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.0, 0.1, curve: Curves.easeOut))); + parent: _controller, + curve: const Interval(0.0, 0.1, curve: Curves.easeOut))); _fadeOut = Tween(begin: 1.0, end: 1.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.9, 1.0, curve: Curves.easeIn))); + parent: _controller, + curve: const Interval(0.9, 1.0, curve: Curves.easeIn))); _colorShifter = Tween(begin: 0.0, end: widget.colors.length * _tuning).animate( CurvedAnimation( parent: _controller, - curve: Interval(0.0, 1.0, curve: Curves.easeIn))) + curve: const Interval(0.0, 1.0, curve: Curves.easeIn))) ..addStatusListener(_animationEndCallback); _controller?.forward(); diff --git a/lib/src/fade.dart b/lib/src/fade.dart index 6086e00..5a64c7d 100644 --- a/lib/src/fade.dart +++ b/lib/src/fade.dart @@ -4,7 +4,7 @@ import 'dart:math'; class FadeAnimatedTextKit extends StatefulWidget { /// List of [String] that would be displayed subsequently in the animation. - final List text; + final List text; /// Gives [TextStyle] to the text strings. final TextStyle textStyle; @@ -32,12 +32,12 @@ class FadeAnimatedTextKit extends StatefulWidget { /// Adds the onNext [VoidCallback] to the animated widget. /// /// Will be called right before the next text, after the pause parameter - final Function onNext; + final void Function(int, bool) onNext; /// Adds the onNextBeforePause [VoidCallback] to the animated widget. /// /// Will be called at the end of n-1 animation, before the pause parameter - final Function onNextBeforePause; + final void Function(int, bool) onNextBeforePause; /// Adds [AlignmentGeometry] property to the text in the widget. /// @@ -95,10 +95,10 @@ class FadeAnimatedTextKit extends StatefulWidget { : super(key: key); @override - _RotatingTextState createState() => new _RotatingTextState(); + _FadeTextState createState() => _FadeTextState(); } -class _RotatingTextState extends State +class _FadeTextState extends State with TickerProviderStateMixin { Animation _fadeIn, _fadeOut; @@ -107,7 +107,7 @@ class _RotatingTextState extends State Duration _pause; - List _texts = []; + List> _texts = []; int _index; @@ -123,39 +123,25 @@ class _RotatingTextState extends State void initState() { super.initState(); - _pause = widget.pause ?? Duration(milliseconds: 500); + _pause = widget.pause ?? const Duration(milliseconds: 500); _index = -1; _currentRepeatCount = 0; - if (widget.duration == null) { - _duration = Duration(milliseconds: 2000); - } else { - _duration = widget.duration; - } + _duration = widget.duration ?? const Duration(milliseconds: 2000); + + widget.text.forEach((text) { + _texts.add({'text': text, 'pause': _pause}); + }); - for (int i = 0; i < widget.text.length; i++) { - try { - if (!widget.text[i].containsKey('text')) throw Error(); - - _texts.add({ - 'text': widget.text[i]['text'], - 'pause': widget.text[i].containsKey('pause') - ? widget.text[i]['pause'] - : _pause - }); - } catch (e) { - _texts.add({'text': widget.text[i], 'pause': _pause}); - } - } _nextAnimation(); } @override void dispose() { _controller?.stop(); - _controller.dispose(); + _controller?.dispose(); super.dispose(); } @@ -173,9 +159,8 @@ class _RotatingTextState extends State animation: _controller, builder: (BuildContext context, Widget child) { return Opacity( - opacity: !(_fadeIn.value == 1.0) - ? _fadeIn.value - : _fadeOut.value, + opacity: + _fadeIn.value != 1.0 ? _fadeIn.value : _fadeOut.value, child: Text( _texts[_index]['text'], style: widget.textStyle, @@ -187,13 +172,13 @@ class _RotatingTextState extends State } void _nextAnimation() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = false; // Handling onNext callback if (_index > -1) { - if (widget.onNext != null) widget.onNext(_index, isLast); + widget.onNext?.call(_index, isLast); } if (isLast) { @@ -205,7 +190,7 @@ class _RotatingTextState extends State _currentRepeatCount++; } } else { - if (widget.onFinished != null) widget.onFinished(); + widget.onFinished?.call(); return; } } else { @@ -214,30 +199,31 @@ class _RotatingTextState extends State if (mounted) setState(() {}); - _controller = new AnimationController( + _controller = AnimationController( duration: _duration, vsync: this, ); _fadeIn = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.0, 0.5, curve: Curves.linear))); + parent: _controller, + curve: const Interval(0.0, 0.5, curve: Curves.linear))); _fadeOut = Tween(begin: 1.0, end: 0.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.8, 1.0, curve: Curves.linear))) + parent: _controller, + curve: const Interval(0.8, 1.0, curve: Curves.linear))) ..addStatusListener(_animationEndCallback); _controller.forward(); } void _setPause() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = true; if (mounted) setState(() {}); // Handle onNextBeforePause callback - if (widget.onNextBeforePause != null) - widget.onNextBeforePause(_index, isLast); + widget.onNextBeforePause?.call(_index, isLast); } void _animationEndCallback(state) { @@ -248,9 +234,6 @@ class _RotatingTextState extends State } void _onTap() { - int pause; - int left; - if (widget.displayFullTextOnTap) { if (_isCurrentlyPausing) { if (widget.stopPauseOnTap) { @@ -258,8 +241,8 @@ class _RotatingTextState extends State _nextAnimation(); } } else { - pause = _texts[_index]['pause'].inMilliseconds; - left = widget.duration.inMilliseconds; + final int pause = _texts[_index]['pause'].inMilliseconds; + final int left = widget.duration.inMilliseconds; _controller?.stop(); @@ -270,8 +253,6 @@ class _RotatingTextState extends State } } - if (widget.onTap != null) { - widget.onTap(); - } + widget.onTap?.call(); } } diff --git a/lib/src/rotate.dart b/lib/src/rotate.dart index 6d8bbe6..264e632 100644 --- a/lib/src/rotate.dart +++ b/lib/src/rotate.dart @@ -3,7 +3,7 @@ import 'dart:async'; class RotateAnimatedTextKit extends StatefulWidget { /// List of [String] that would be displayed subsequently in the animation. - final List text; + final List text; /// Gives [TextStyle] to the text strings. final TextStyle textStyle; @@ -36,12 +36,12 @@ class RotateAnimatedTextKit extends StatefulWidget { /// Adds the onNext [VoidCallback] to the animated widget. /// /// Will be called right before the next text, after the pause parameter - final Function onNext; + final void Function(int, bool) onNext; /// Adds the onNextBeforePause [VoidCallback] to the animated widget. /// /// Will be called at the end of n-1 animation, before the pause parameter - final Function onNextBeforePause; + final void Function(int, bool) onNextBeforePause; /// Adds [AlignmentGeometry] property to the text in the widget. /// @@ -94,7 +94,7 @@ class RotateAnimatedTextKit extends StatefulWidget { : super(key: key); @override - _RotatingTextState createState() => new _RotatingTextState(); + _RotatingTextState createState() => _RotatingTextState(); } class _RotatingTextState extends State @@ -109,7 +109,7 @@ class _RotatingTextState extends State Duration _pause; - List _texts = []; + List> _texts = []; int _index; @@ -125,32 +125,17 @@ class _RotatingTextState extends State void initState() { super.initState(); - _pause = widget.pause ?? Duration(milliseconds: 500); + _pause = widget.pause ?? const Duration(milliseconds: 500); _index = -1; _currentRepeatCount = 0; - if (widget.duration == null) { - _duration = Duration(milliseconds: 2000); - } else { - _duration = widget.duration; - } + _duration = widget.duration ?? const Duration(milliseconds: 2000); - for (int i = 0; i < widget.text.length; i++) { - try { - if (!widget.text[i].containsKey('text')) throw Error(); - - _texts.add({ - 'text': widget.text[i]['text'], - 'pause': widget.text[i].containsKey('pause') - ? widget.text[i]['pause'] - : _pause - }); - } catch (e) { - _texts.add({'text': widget.text[i], 'pause': _pause}); - } - } + widget.text.forEach((text) { + _texts.add({'text': text, 'pause': _pause}); + }); _nextAnimation(); } @@ -196,13 +181,13 @@ class _RotatingTextState extends State } void _nextAnimation() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = false; // Handling onNext callback if (_index > -1) { - if (widget.onNext != null) widget.onNext(_index, isLast); + widget.onNext?.call(_index, isLast); } if (isLast) { @@ -214,7 +199,7 @@ class _RotatingTextState extends State _currentRepeatCount++; } } else { - if (widget.onFinished != null) widget.onFinished(); + widget.onFinished?.call(); return; } } else { @@ -229,7 +214,7 @@ class _RotatingTextState extends State _transitionHeight = widget.transitionHeight; } - _controller = new AnimationController( + _controller = AnimationController( duration: _duration, vsync: this, ); @@ -251,35 +236,36 @@ class _RotatingTextState extends State end: Alignment(-1.0, 0.0).add(widget.alignment)) .animate(CurvedAnimation( parent: _controller, - curve: Interval(0.0, 0.4, curve: Curves.linear))); + curve: const Interval(0.0, 0.4, curve: Curves.linear))); _fadeIn = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( parent: _controller, - curve: Interval(0.0, 0.4, curve: Curves.easeOut))); + curve: const Interval(0.0, 0.4, curve: Curves.easeOut))); } _slideOut = AlignmentTween( begin: Alignment(-1.0, 0.0).add(widget.alignment), - end: new Alignment(-1.0, 1.0).add(widget.alignment), + end: Alignment(-1.0, 1.0).add(widget.alignment), ).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.7, 1.0, curve: Curves.linear))); + parent: _controller, + curve: const Interval(0.7, 1.0, curve: Curves.linear))); _fadeOut = Tween(begin: 1.0, end: 0.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.7, 1.0, curve: Curves.easeIn))) + parent: _controller, + curve: const Interval(0.7, 1.0, curve: Curves.easeIn))) ..addStatusListener(_animationEndCallback); _controller.forward(); } void _setPause() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = true; if (mounted) setState(() {}); // Handle onNextBeforePause callback - if (widget.onNextBeforePause != null) - widget.onNextBeforePause(_index, isLast); + widget.onNextBeforePause?.call(_index, isLast); } void _animationEndCallback(state) { @@ -289,25 +275,19 @@ class _RotatingTextState extends State } void _onTap() { - int pause; - if (widget.displayFullTextOnTap) { if (_isCurrentlyPausing) { _timer?.cancel(); _nextAnimation(); } else { - pause = _texts[_index]['pause'].inMilliseconds; - _controller?.stop(); _setPause(); - _timer = Timer(Duration(milliseconds: pause), _nextAnimation); + _timer = Timer(_texts[_index]['pause'], _nextAnimation); } } - if (widget.onTap != null) { - widget.onTap(); - } + widget.onTap?.call(); } } diff --git a/lib/src/scale.dart b/lib/src/scale.dart index 53befd2..51749ca 100644 --- a/lib/src/scale.dart +++ b/lib/src/scale.dart @@ -4,7 +4,7 @@ import 'dart:math'; class ScaleAnimatedTextKit extends StatefulWidget { /// List of [String] that would be displayed subsequently in the animation. - final List text; + final List text; /// Gives [TextStyle] to the text strings. final TextStyle textStyle; @@ -32,12 +32,12 @@ class ScaleAnimatedTextKit extends StatefulWidget { /// Adds the onNext [VoidCallback] to the animated widget. /// /// Will be called right before the next text, after the pause parameter - final Function onNext; + final void Function(int, bool) onNext; /// Adds the onNextBeforePause [VoidCallback] to the animated widget. /// /// Will be called at the end of n-1 animation, before the pause parameter - final Function onNextBeforePause; + final void Function(int, bool) onNextBeforePause; /// Adds [AlignmentGeometry] property to the text in the widget. /// @@ -101,7 +101,7 @@ class ScaleAnimatedTextKit extends StatefulWidget { : super(key: key); @override - _RotatingTextState createState() => new _RotatingTextState(); + _RotatingTextState createState() => _RotatingTextState(); } class _RotatingTextState extends State @@ -113,7 +113,7 @@ class _RotatingTextState extends State Duration _pause; - List _texts = []; + List> _texts = []; int _index; @@ -129,32 +129,17 @@ class _RotatingTextState extends State void initState() { super.initState(); - _pause = widget.pause ?? Duration(milliseconds: 500); + _pause = widget.pause ?? const Duration(milliseconds: 500); _index = -1; _currentRepeatCount = 0; - if (widget.duration == null) { - _duration = Duration(milliseconds: 2000); - } else { - _duration = widget.duration; - } + _duration = widget.duration ?? const Duration(milliseconds: 2000); - for (int i = 0; i < widget.text.length; i++) { - try { - if (!widget.text[i].containsKey('text')) throw Error(); - - _texts.add({ - 'text': widget.text[i]['text'], - 'pause': widget.text[i].containsKey('pause') - ? widget.text[i]['pause'] - : _pause - }); - } catch (e) { - _texts.add({'text': widget.text[i], 'pause': _pause}); - } - } + widget.text.forEach((text) { + _texts.add({'text': text, 'pause': _pause}); + }); // Start animation _nextAnimation(); @@ -198,13 +183,13 @@ class _RotatingTextState extends State } void _nextAnimation() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = false; // Handling onNext callback if (_index > -1) { - if (widget.onNext != null) widget.onNext(_index, isLast); + widget.onNext?.call(_index, isLast); } if (isLast) { @@ -216,7 +201,7 @@ class _RotatingTextState extends State _currentRepeatCount++; } } else { - if (widget.onFinished != null) widget.onFinished(); + widget.onFinished?.call(); return; } } else { @@ -225,21 +210,23 @@ class _RotatingTextState extends State setState(() {}); - _controller = new AnimationController( + _controller = AnimationController( duration: _duration, vsync: this, ); _fadeIn = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.0, 0.5, curve: Curves.easeOut))); + parent: _controller, + curve: const Interval(0.0, 0.5, curve: Curves.easeOut))); _fadeOut = Tween(begin: 1.0, end: 0.0).animate(CurvedAnimation( - parent: _controller, curve: Interval(0.5, 1.0, curve: Curves.easeOut))); + parent: _controller, + curve: const Interval(0.5, 1.0, curve: Curves.easeOut))); _scaleIn = Tween(begin: widget.scalingFactor, end: 1.0) .animate(CurvedAnimation( parent: _controller, - curve: Interval( + curve: const Interval( 0.0, 0.5, curve: Curves.easeOut, @@ -247,7 +234,7 @@ class _RotatingTextState extends State _scaleOut = Tween(begin: 1.0, end: widget.scalingFactor) .animate(CurvedAnimation( parent: _controller, - curve: Interval( + curve: const Interval( 0.5, 1.0, curve: Curves.easeIn, @@ -258,14 +245,13 @@ class _RotatingTextState extends State } void _setPause() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = true; setState(() {}); // Handle onNextBeforePause callback - if (widget.onNextBeforePause != null) - widget.onNextBeforePause(_index, isLast); + widget.onNextBeforePause?.call(_index, isLast); } void _animationEndCallback(state) { @@ -276,9 +262,6 @@ class _RotatingTextState extends State } void _onTap() { - int pause; - int left; - if (widget.displayFullTextOnTap) { if (_isCurrentlyPausing) { if (widget.stopPauseOnTap) { @@ -286,8 +269,8 @@ class _RotatingTextState extends State _nextAnimation(); } } else { - pause = _texts[_index]['pause'].inMilliseconds; - left = _duration.inMilliseconds; + final int pause = _texts[_index]['pause'].inMilliseconds; + final int left = _duration.inMilliseconds; _controller.stop(); @@ -298,8 +281,6 @@ class _RotatingTextState extends State } } - if (widget.onTap != null) { - widget.onTap(); - } + widget.onTap?.call(); } } diff --git a/lib/src/text_liquid_fill.dart b/lib/src/text_liquid_fill.dart index 66a8c99..e31380c 100644 --- a/lib/src/text_liquid_fill.dart +++ b/lib/src/text_liquid_fill.dart @@ -53,7 +53,7 @@ class TextLiquidFill extends StatefulWidget { : super(key: key); @override - _TextLiquidFillState createState() => new _TextLiquidFillState(); + _TextLiquidFillState createState() => _TextLiquidFillState(); } class _TextLiquidFillState extends State @@ -79,9 +79,9 @@ class _TextLiquidFillState extends State _boxWidth = widget.boxWidth ?? 400; - _waveDuration = widget.waveDuration ?? Duration(milliseconds: 2000); + _waveDuration = widget.waveDuration ?? const Duration(milliseconds: 2000); - _loadDuration = widget.loadDuration ?? Duration(milliseconds: 6000); + _loadDuration = widget.loadDuration ?? const Duration(milliseconds: 6000); _waveController = AnimationController(vsync: this, duration: _waveDuration); diff --git a/lib/src/typer.dart b/lib/src/typer.dart index ecd491f..3969adc 100644 --- a/lib/src/typer.dart +++ b/lib/src/typer.dart @@ -4,7 +4,7 @@ import 'dart:async'; class TyperAnimatedTextKit extends StatefulWidget { /// List of [String] that would be displayed subsequently in the animation. - final List text; + final List text; /// Gives [TextStyle] to the text strings. final TextStyle textStyle; @@ -30,12 +30,12 @@ class TyperAnimatedTextKit extends StatefulWidget { /// Adds the onNext [VoidCallback] to the animated widget. /// /// Will be called right before the next text, after the pause parameter - final Function onNext; + final void Function(int, bool) onNext; /// Adds the onNextBeforePause [VoidCallback] to the animated widget. /// /// Will be called at the end of n-1 animation, before the pause parameter - final Function onNextBeforePause; + final void Function(int, bool) onNextBeforePause; /// Adds [AlignmentGeometry] property to the text in the widget. /// @@ -80,7 +80,7 @@ class TyperAnimatedTextKit extends StatefulWidget { }) : super(key: key); @override - _TyperState createState() => new _TyperState(); + _TyperState createState() => _TyperState(); } class _TyperState extends State @@ -92,7 +92,7 @@ class _TyperState extends State Duration _speed; Duration _pause; - List _texts = []; + List> _texts = []; int _index; @@ -104,28 +104,14 @@ class _TyperState extends State void initState() { super.initState(); - _speed = widget.speed ?? Duration(milliseconds: 40); - _pause = widget.pause ?? Duration(milliseconds: 1000); + _speed = widget.speed ?? const Duration(milliseconds: 40); + _pause = widget.pause ?? const Duration(milliseconds: 1000); _index = -1; - for (int i = 0; i < widget.text.length; i++) { - try { - if (!widget.text[i].containsKey('text')) throw new Error(); - - _texts.add({ - 'text': widget.text[i]['text'], - 'speed': widget.text[i].containsKey('speed') - ? widget.text[i]['speed'] - : _speed, - 'pause': widget.text[i].containsKey('pause') - ? widget.text[i]['pause'] - : _pause, - }); - } catch (e) { - _texts.add({'text': widget.text[i], 'speed': _speed, 'pause': _pause}); - } - } + widget.text.forEach((text) { + _texts.add({'text': text, 'speed': _speed, 'pause': _pause}); + }); // Start animation _nextAnimation(); @@ -151,9 +137,10 @@ class _TyperState extends State : AnimatedBuilder( animation: _controller, builder: (BuildContext context, Widget child) { - int offset = _texts[_index]['text'].length < _typingText.value - ? _texts[_index]['text'].length - : _typingText.value; + final int offset = + _texts[_index]['text'].length < _typingText.value + ? _texts[_index]['text'].length + : _typingText.value; return Text( _texts[_index]['text'].substring(0, offset), @@ -165,20 +152,20 @@ class _TyperState extends State } void _nextAnimation() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = false; // Handling onNext callback if (_index > -1) { - if (widget.onNext != null) widget.onNext(_index, isLast); + widget.onNext?.call(_index, isLast); } if (isLast) { if (widget.isRepeatingAnimation) { _index = 0; } else { - if (widget.onFinished != null) widget.onFinished(); + widget.onFinished?.call(); return; } } else { @@ -187,7 +174,7 @@ class _TyperState extends State if (mounted) setState(() {}); - _controller = new AnimationController( + _controller = AnimationController( duration: _texts[_index]['speed'] * _texts[_index]['text'].length, vsync: this, ); @@ -200,14 +187,13 @@ class _TyperState extends State } void _setPause() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = true; if (mounted) setState(() {}); // Handle onNextBeforePause callback - if (widget.onNextBeforePause != null) - widget.onNextBeforePause(_index, isLast); + widget.onNextBeforePause?.call(_index, isLast); } void _animationEndCallback(state) { @@ -218,9 +204,6 @@ class _TyperState extends State } void _onTap() { - int pause; - int left; - if (widget.displayFullTextOnTap) { if (_isCurrentlyPausing) { if (widget.stopPauseOnTap) { @@ -228,8 +211,8 @@ class _TyperState extends State _nextAnimation(); } } else { - pause = _texts[_index]['pause'].inMilliseconds; - left = _texts[_index]['speed'].inMilliseconds * + final int pause = _texts[_index]['pause'].inMilliseconds; + final int left = _texts[_index]['speed'].inMilliseconds * (_texts[_index]['text'].length - _typingText.value); _controller.stop(); @@ -241,8 +224,6 @@ class _TyperState extends State } } - if (widget.onTap != null) { - widget.onTap(); - } + widget.onTap?.call(); } } diff --git a/lib/src/typewriter.dart b/lib/src/typewriter.dart index 7770b85..874e9dd 100644 --- a/lib/src/typewriter.dart +++ b/lib/src/typewriter.dart @@ -4,7 +4,7 @@ import 'dart:math'; class TypewriterAnimatedTextKit extends StatefulWidget { /// List of [String] that would be displayed subsequently in the animation. - final List text; + final List text; /// Gives [TextStyle] to the text strings. final TextStyle textStyle; @@ -30,12 +30,12 @@ class TypewriterAnimatedTextKit extends StatefulWidget { /// Adds the onNext [VoidCallback] to the animated widget. /// /// Will be called right before the next text, after the pause parameter - final Function onNext; + final void Function(int, bool) onNext; /// Adds the onNextBeforePause [VoidCallback] to the animated widget. /// /// Will be called at the end of n-1 animation, before the pause parameter - final Function onNextBeforePause; + final void Function(int, bool) onNextBeforePause; /// Adds [AlignmentGeometry] property to the text in the widget. /// @@ -94,7 +94,7 @@ class TypewriterAnimatedTextKit extends StatefulWidget { super(key: key); @override - _TypewriterState createState() => new _TypewriterState(); + _TypewriterState createState() => _TypewriterState(); } class _TypewriterState extends State @@ -107,7 +107,7 @@ class _TypewriterState extends State Duration _speed; Duration _pause; - List _texts = []; + List> _texts = []; int _index; @@ -121,30 +121,16 @@ class _TypewriterState extends State void initState() { super.initState(); - _speed = widget.speed ?? Duration(milliseconds: 30); - _pause = widget.pause ?? Duration(milliseconds: 1000); + _speed = widget.speed ?? const Duration(milliseconds: 30); + _pause = widget.pause ?? const Duration(milliseconds: 1000); _index = -1; _currentRepeatCount = 0; - for (int i = 0; i < widget.text.length; i++) { - try { - if (!widget.text[i].containsKey('text')) throw Error(); - - _texts.add({ - 'text': widget.text[i]['text'], - 'speed': widget.text[i].containsKey('speed') - ? widget.text[i]['speed'] - : _speed, - 'pause': widget.text[i].containsKey('pause') - ? widget.text[i]['pause'] - : _pause - }); - } catch (e) { - _texts.add({'text': widget.text[i], 'speed': _speed, 'pause': _pause}); - } - } + widget.text.forEach((text) { + _texts.add({'text': text, 'speed': _speed, 'pause': _pause}); + }); _nextAnimation(); } @@ -201,13 +187,13 @@ class _TypewriterState extends State } void _nextAnimation() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = false; // Handling onNext callback if (_index > -1) { - if (widget.onNext != null) widget.onNext(_index, isLast); + widget.onNext?.call(_index, isLast); } if (isLast) { @@ -219,7 +205,7 @@ class _TypewriterState extends State _currentRepeatCount++; } } else { - if (widget.onFinished != null) widget.onFinished(); + widget.onFinished?.call(); return; } } else { @@ -228,7 +214,7 @@ class _TypewriterState extends State if (mounted) setState(() {}); - _controller = new AnimationController( + _controller = AnimationController( duration: _texts[_index]['speed'] * _texts[_index]['text'].length, vsync: this, ); @@ -242,7 +228,7 @@ class _TypewriterState extends State } void _setPause() { - bool isLast = _index == widget.text.length - 1; + final bool isLast = _index == widget.text.length - 1; _isCurrentlyPausing = true; if (mounted) setState(() {}); @@ -260,9 +246,6 @@ class _TypewriterState extends State } void _onTap() { - int pause; - int left; - if (widget.displayFullTextOnTap) { if (_isCurrentlyPausing) { if (widget.stopPauseOnTap) { @@ -270,8 +253,8 @@ class _TypewriterState extends State _nextAnimation(); } } else { - pause = _texts[_index]['pause'].inMilliseconds; - left = _texts[_index]['speed'].inMilliseconds * + final int pause = _texts[_index]['pause'].inMilliseconds; + final int left = _texts[_index]['speed'].inMilliseconds * (_texts[_index]['text'].length - _typewriterText.value); _controller.stop(); @@ -283,8 +266,6 @@ class _TypewriterState extends State } } - if (widget.onTap != null) { - widget.onTap(); - } + widget.onTap?.call(); } } diff --git a/test/animated_text_kit_test.dart b/test/animated_text_kit_test.dart index d11231d..4d8aa19 100644 --- a/test/animated_text_kit_test.dart +++ b/test/animated_text_kit_test.dart @@ -5,7 +5,7 @@ import '../example/lib/main.dart'; void main() { testWidgets('Check button smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(new MyApp()); + await tester.pumpWidget(MyApp()); expect(find.text(labels[0]), findsOneWidget); From 42f4af8ab612c0ebcf30d07d5bc4344f3d4077be Mon Sep 17 00:00:00 2001 From: Anthony Whitford Date: Sun, 24 May 2020 17:27:28 -0700 Subject: [PATCH 2/4] Renamed more internal State classes to match their counterpart Stateful Widget name better. --- lib/src/colorize.dart | 4 ++-- lib/src/scale.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/colorize.dart b/lib/src/colorize.dart index e0938ac..934571c 100644 --- a/lib/src/colorize.dart +++ b/lib/src/colorize.dart @@ -80,10 +80,10 @@ class ColorizeAnimatedTextKit extends StatefulWidget { : super(key: key); @override - _RotatingTextState createState() => _RotatingTextState(); + _ColorizeTextState createState() => _ColorizeTextState(); } -class _RotatingTextState extends State +class _ColorizeTextState extends State with TickerProviderStateMixin { AnimationController _controller; diff --git a/lib/src/scale.dart b/lib/src/scale.dart index 51749ca..5fb844a 100644 --- a/lib/src/scale.dart +++ b/lib/src/scale.dart @@ -101,10 +101,10 @@ class ScaleAnimatedTextKit extends StatefulWidget { : super(key: key); @override - _RotatingTextState createState() => _RotatingTextState(); + _ScaleTextState createState() => _ScaleTextState(); } -class _RotatingTextState extends State +class _ScaleTextState extends State with TickerProviderStateMixin { AnimationController _controller; From 517014439ba1b81631c16263acca6ec58d155513 Mon Sep 17 00:00:00 2001 From: Anthony Whitford Date: Mon, 25 May 2020 13:29:39 -0700 Subject: [PATCH 3/4] Further optimization for AnimatedBuilder. --- lib/src/fade.dart | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/lib/src/fade.dart b/lib/src/fade.dart index d37ec7c..ca5cb9f 100644 --- a/lib/src/fade.dart +++ b/lib/src/fade.dart @@ -147,28 +147,27 @@ class _FadeTextState extends State @override Widget build(BuildContext context) { + final textWidget = Text( + _texts[_index]['text'], + style: widget.textStyle, + textAlign: widget.textAlign, + ); return GestureDetector( - onTap: _onTap, - child: _isCurrentlyPausing || !_controller.isAnimating - ? Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ) - : AnimatedBuilder( - animation: _controller, - builder: (BuildContext context, Widget child) { - return Opacity( - opacity: - _fadeIn.value != 1.0 ? _fadeIn.value : _fadeOut.value, - child: Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ), - ); - }, - )); + onTap: _onTap, + child: _isCurrentlyPausing || !_controller.isAnimating + ? textWidget + : AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, Widget child) { + return Opacity( + opacity: + _fadeIn.value != 1.0 ? _fadeIn.value : _fadeOut.value, + child: child, + ); + }, + child: textWidget, + ), + ); } void _nextAnimation() { From c1619489ec79a539b8c9184b7b0bf3045ceacc18 Mon Sep 17 00:00:00 2001 From: Anthony Whitford Date: Mon, 25 May 2020 13:43:10 -0700 Subject: [PATCH 4/4] More consistency. Simplified some comparison expressions, added child to some AnimatedBuilders, and added const keyword. --- lib/src/colorize.dart | 56 +++++++++++++++++++-------------------- lib/src/fade.dart | 2 +- lib/src/rotate.dart | 58 ++++++++++++++++++++--------------------- lib/src/scale.dart | 48 ++++++++++++++++------------------ lib/src/typewriter.dart | 2 +- 5 files changed, 81 insertions(+), 85 deletions(-) diff --git a/lib/src/colorize.dart b/lib/src/colorize.dart index 06c1966..01850f4 100644 --- a/lib/src/colorize.dart +++ b/lib/src/colorize.dart @@ -128,34 +128,34 @@ class _ColorizeTextState extends State @override Widget build(BuildContext context) { return GestureDetector( - onTap: widget.onTap, - child: _isCurrentlyPausing || !_controller.isAnimating - ? Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ) - : AnimatedBuilder( - animation: _controller, - builder: (BuildContext context, Widget child) { - Shader linearGradient = LinearGradient(colors: widget.colors) - .createShader( - Rect.fromLTWH(0.0, 0.0, _colorShifter.value, 0.0)); - return Opacity( - opacity: !(_fadeIn.value == 1.0) - ? _fadeIn.value - : _fadeOut.value, - child: Text( - _texts[_index]['text'], - style: widget.textStyle != null - ? widget.textStyle.merge(TextStyle( - foreground: Paint()..shader = linearGradient)) - : widget.textStyle, - textAlign: widget.textAlign, - ), - ); - }, - )); + onTap: widget.onTap, + child: _isCurrentlyPausing || !_controller.isAnimating + ? Text( + _texts[_index]['text'], + style: widget.textStyle, + textAlign: widget.textAlign, + ) + : AnimatedBuilder( + animation: _controller, + builder: (BuildContext context, Widget child) { + Shader linearGradient = LinearGradient(colors: widget.colors) + .createShader( + Rect.fromLTWH(0.0, 0.0, _colorShifter.value, 0.0)); + return Opacity( + opacity: + _fadeIn.value != 1.0 ? _fadeIn.value : _fadeOut.value, + child: Text( + _texts[_index]['text'], + style: widget.textStyle != null + ? widget.textStyle.merge(TextStyle( + foreground: Paint()..shader = linearGradient)) + : widget.textStyle, + textAlign: widget.textAlign, + ), + ); + }, + ), + ); } void _nextAnimation() { diff --git a/lib/src/fade.dart b/lib/src/fade.dart index ca5cb9f..e7b4d85 100644 --- a/lib/src/fade.dart +++ b/lib/src/fade.dart @@ -158,6 +158,7 @@ class _FadeTextState extends State ? textWidget : AnimatedBuilder( animation: _controller, + child: textWidget, builder: (BuildContext context, Widget child) { return Opacity( opacity: @@ -165,7 +166,6 @@ class _FadeTextState extends State child: child, ); }, - child: textWidget, ), ); } diff --git a/lib/src/rotate.dart b/lib/src/rotate.dart index 8c5664b..7a8d5fe 100644 --- a/lib/src/rotate.dart +++ b/lib/src/rotate.dart @@ -149,35 +149,33 @@ class _RotatingTextState extends State @override Widget build(BuildContext context) { + final textWidget = Text( + _texts[_index]['text'], + style: widget.textStyle, + textAlign: widget.textAlign, + ); return GestureDetector( - onTap: _onTap, - child: SizedBox( - height: _transitionHeight, - child: _isCurrentlyPausing || !_controller.isAnimating - ? Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ) - : AnimatedBuilder( - animation: _controller, - child: Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ), - builder: (BuildContext context, Widget child) { - return AlignTransition( - alignment: - !(_slideIn.value.y == 0.0) ? _slideIn : _slideOut, - child: Opacity( - opacity: !(_fadeIn.value == 1.0) - ? _fadeIn.value - : _fadeOut.value, - child: child), - ); - }, - ))); + onTap: _onTap, + child: SizedBox( + height: _transitionHeight, + child: _isCurrentlyPausing || !_controller.isAnimating + ? textWidget + : AnimatedBuilder( + animation: _controller, + child: textWidget, + builder: (BuildContext context, Widget child) { + return AlignTransition( + alignment: _slideIn.value.y != 0.0 ? _slideIn : _slideOut, + child: Opacity( + opacity: _fadeIn.value != 1.0 + ? _fadeIn.value + : _fadeOut.value, + child: child), + ); + }, + ), + ), + ); } void _nextAnimation() { @@ -225,11 +223,11 @@ class _RotatingTextState extends State end: Alignment(-1.0, 0.0).add(widget.alignment)) .animate(CurvedAnimation( parent: _controller, - curve: Interval(0.0, 0.4, curve: Curves.linear))); + curve: const Interval(0.0, 0.4, curve: Curves.linear))); _fadeIn = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( parent: _controller, - curve: Interval(0.0, 0.4, curve: Curves.easeOut))); + curve: const Interval(0.0, 0.4, curve: Curves.easeOut))); } else { _slideIn = AlignmentTween( begin: Alignment(-1.0, -1.0).add(widget.alignment), diff --git a/lib/src/scale.dart b/lib/src/scale.dart index 19a3e05..288bb20 100644 --- a/lib/src/scale.dart +++ b/lib/src/scale.dart @@ -154,32 +154,30 @@ class _ScaleTextState extends State @override Widget build(BuildContext context) { + final textWidget = Text( + _texts[_index]['text'], + style: widget.textStyle, + textAlign: widget.textAlign, + ); return GestureDetector( - onTap: _onTap, - child: _isCurrentlyPausing || !_controller.isAnimating - ? Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ) - : AnimatedBuilder( - animation: _controller, - builder: (BuildContext context, Widget child) { - return ScaleTransition( - scale: !(_scaleIn.value == 1.0) ? _scaleIn : _scaleOut, - child: Opacity( - opacity: !(_fadeIn.value == 1.0) - ? _fadeIn.value - : _fadeOut.value, - child: Text( - _texts[_index]['text'], - style: widget.textStyle, - textAlign: widget.textAlign, - ), - ), - ); - }, - )); + onTap: _onTap, + child: _isCurrentlyPausing || !_controller.isAnimating + ? textWidget + : AnimatedBuilder( + animation: _controller, + child: textWidget, + builder: (BuildContext context, Widget child) { + return ScaleTransition( + scale: _scaleIn.value != 1.0 ? _scaleIn : _scaleOut, + child: Opacity( + opacity: + _fadeIn.value != 1.0 ? _fadeIn.value : _fadeOut.value, + child: child, + ), + ); + }, + ), + ); } void _nextAnimation() { diff --git a/lib/src/typewriter.dart b/lib/src/typewriter.dart index 75fd872..20a9439 100644 --- a/lib/src/typewriter.dart +++ b/lib/src/typewriter.dart @@ -90,7 +90,7 @@ class TypewriterAnimatedTextKit extends StatefulWidget { this.textAlign = TextAlign.start, this.repeatForever = false, this.isRepeatingAnimation = true}) - : assert(!(text == null), 'You should specify the list of text'), + : assert(text != null, 'You must specify the list of text'), super(key: key); @override