├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example └── main.dart ├── lib ├── src │ ├── ease.dart │ ├── miticker.dart │ └── tweener.dart └── tweener.dart ├── pubspec.yaml └── test └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | .dart_tool 4 | pubspec.lock -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.2 2 | 3 | - Add CHANGELOG.md file 4 | 5 | ## 1.1.1 6 | 7 | - Modify some method names 8 | - Add more easing functions 9 | 10 | ## 1.1.0 11 | 12 | - Modify the micketer structure -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2019 tweener authors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tweener 2 | 3 | Tweener is a simple and lightweight flutter animation tool. Anyone can easily learn to use it. 4 | 5 | ## Features 6 | 7 | * Does one thing and one thing only: tween properties 8 | * Very simple to use, but it can achieve a lot of effects 9 | * Easing functions are reusable outside of Tween 10 | 11 | ## Installation 12 | 13 | > Install the Tweener [https://pub.dev/packages/tweener](https://pub.dev/packages/tweener): 14 | 15 | #### You should ensure that you add the following dependency in your Flutter project. 16 | ``` 17 | dependencies: 18 | tweener: ^2.2.2 19 | ``` 20 | 21 | #### install packages from the command line: 22 | ``` 23 | flutter packages get 24 | ``` 25 | 26 | ## Useage 27 | 28 | #### import class 29 | ``` 30 | import 'package:tweener/tweener.dart'; 31 | ``` 32 | 33 | #### use Tweener 34 | ``` 35 | Tweener({"x": 0, "y": 0, "alpha": 0, "custom_prop_abc": 123}) 36 | .to({"x": 100, "y": 500, "alpha": 1, "custom_prop_abc": 321}, 2000) 37 | .easing(Tweener.ease.elastic.easeOut) 38 | .onUpdate((obj) { 39 | setState(() { 40 | _x = obj["x"]; 41 | _y = obj["y"]; 42 | _alpha = obj["alpha"]; 43 | _abc = obj["custom_prop_abc"]; 44 | }); 45 | }) 46 | .onComplete((obj){ 47 | /// 48 | }) 49 | .start(); 50 | ``` 51 | 52 | ``` 53 | var tween1 = new Tweener(sprite) 54 | .to({x: 700, y: 200, rotation: 359}, 2000) 55 | .delay(1000) 56 | .easing(Ease.back.easeOut) 57 | .onUpdate(update); 58 | 59 | var tween2 = new Tweener(sprite) 60 | .to({x: 10, y: 20, rotation: 30}, 2000) 61 | .onUpdate(update); 62 | 63 | tween1.chain(tween2); 64 | tween1.start(); 65 | ``` 66 | ## About AnimateCon 67 | 68 | To operate widget animations more conveniently, you can utilize the [AnimateCon](https://github.com/flutterkit/AnimateCon) library. This [library](https://github.com/flutterkit/AnimateCon) provides extremely facile implementation methods for animations such as position, scale, and alpha, enabling you to easily create various vivid and interesting animation effects. 69 | 70 | ## Thanks 71 | 72 | Tweener refers to the implementation code of [tween.js](https://github.com/tweenjs/tween.js). They are really great. I want to pay tribute to the original author! 73 | -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:tweener/tweener.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | // This widget is the root of your application. 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | title: 'Flutter Demo', 12 | theme: ThemeData( 13 | // This is the theme of your application. 14 | // 15 | // Try running your application with "flutter run". You'll see the 16 | // application has a blue toolbar. Then, without quitting the app, try 17 | // changing the primarySwatch below to Colors.green and then invoke 18 | // "hot reload" (press "r" in the console where you ran "flutter run", 19 | // or simply save your changes to "hot reload" in a Flutter IDE). 20 | // Notice that the counter didn't reset back to zero; the application 21 | // is not restarted. 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: MyHomePage(title: 'Flutter Demo Home Page'), 25 | ); 26 | } 27 | } 28 | 29 | class MyHomePage extends StatefulWidget { 30 | MyHomePage({Key? key, required this.title}) : super(key: key); 31 | 32 | // This widget is the home page of your application. It is stateful, meaning 33 | // that it has a State object (defined below) that contains fields that affect 34 | // how it looks. 35 | 36 | // This class is the configuration for the state. It holds the values (in this 37 | // case the title) provided by the parent (in this case the App widget) and 38 | // used by the build method of the State. Fields in a Widget subclass are 39 | // always marked "final". 40 | 41 | final String title; 42 | 43 | @override 44 | _MyHomePageState createState() => _MyHomePageState(); 45 | } 46 | 47 | class _MyHomePageState extends State { 48 | double _counter = 0; 49 | 50 | void _incrementCounter() { 51 | Tweener({"x": 0, "y": 0, "alpha": 0, "custom_prop_abc": 123}) 52 | .to({"x": 100, "y": 500, "alpha": 1, "custom_prop_abc": 321}, 2000) 53 | .easing(Ease.elastic.easeOut) 54 | .onUpdate((obj) { 55 | setState(() { 56 | _counter = (obj["x"] * 100).round() * 1.0; 57 | }); 58 | }) 59 | .onComplete((obj) { 60 | /// 61 | }) 62 | .start(); 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | // This method is rerun every time setState is called, for instance as done 68 | // by the _incrementCounter method above. 69 | // 70 | // The Flutter framework has been optimized to make rerunning build methods 71 | // fast, so that you can just rebuild anything that needs updating rather 72 | // than having to individually change instances of widgets. 73 | return Scaffold( 74 | appBar: AppBar( 75 | // Here we take the value from the MyHomePage object that was created by 76 | // the App.build method, and use it to set our appbar title. 77 | title: Text(widget.title), 78 | ), 79 | body: Center( 80 | // Center is a layout widget. It takes a single child and positions it 81 | // in the middle of the parent. 82 | child: Column( 83 | // Column is also layout widget. It takes a list of children and 84 | // arranges them vertically. By default, it sizes itself to fit its 85 | // children horizontally, and tries to be as tall as its parent. 86 | // 87 | // Invoke "debug painting" (press "p" in the console, choose the 88 | // "Toggle Debug Paint" action from the Flutter Inspector in Android 89 | // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) 90 | // to see the wireframe for each widget. 91 | // 92 | // Column has various properties to control how it sizes itself and 93 | // how it positions its children. Here we use mainAxisAlignment to 94 | // center the children vertically; the main axis here is the vertical 95 | // axis because Columns are vertical (the cross axis would be 96 | // horizontal). 97 | mainAxisAlignment: MainAxisAlignment.center, 98 | children: [ 99 | Text( 100 | 'You have pushed the button this many times:', 101 | ), 102 | Text( 103 | '$_counter', 104 | style: Theme.of(context).textTheme.displayMedium, 105 | ), 106 | ], 107 | ), 108 | ), 109 | floatingActionButton: FloatingActionButton( 110 | onPressed: _incrementCounter, 111 | tooltip: 'Increment', 112 | child: Icon(Icons.add), 113 | ), // This trailing comma makes auto-formatting nicer for build methods. 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/src/ease.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | abstract class BaseEasing { 4 | double none(double k); 5 | double easeOut(double k); 6 | double easeInOut(double k); 7 | double easeIn(double k); 8 | } 9 | 10 | class Linear extends BaseEasing { 11 | double none(double k) { 12 | return k; 13 | } 14 | 15 | double easeOut(double k) { 16 | return k; 17 | } 18 | 19 | double easeInOut(double k) { 20 | return k; 21 | } 22 | 23 | double easeIn(double k) { 24 | return k; 25 | } 26 | } 27 | 28 | class Quad extends BaseEasing { 29 | double none(double k) { 30 | return k; 31 | } 32 | 33 | double easeOut(double k) { 34 | return k * (2 - k); 35 | } 36 | 37 | double easeInOut(double k) { 38 | if ((k *= 2) < 1) return 0.5 * k * k; 39 | return -0.5 * (--k * (k - 2) - 1); 40 | } 41 | 42 | double easeIn(double k) { 43 | return k * k; 44 | } 45 | } 46 | 47 | class Cubic extends BaseEasing { 48 | double none(double k) { 49 | return k; 50 | } 51 | 52 | double easeOut(double k) { 53 | return --k * k * k + 1; 54 | } 55 | 56 | double easeInOut(double k) { 57 | if ((k *= 2) < 1) return 0.5 * k * k * k; 58 | return 0.5 * ((k -= 2) * k * k + 2); 59 | } 60 | 61 | double easeIn(double k) { 62 | return k * k * k; 63 | } 64 | } 65 | 66 | class Quart extends BaseEasing { 67 | double none(double k) { 68 | return k; 69 | } 70 | 71 | double easeIn(double k) { 72 | return k * k * k * k; 73 | } 74 | 75 | double easeOut(double k) { 76 | return 1 - --k * k * k * k; 77 | } 78 | 79 | double easeInOut(double k) { 80 | if ((k *= 2) < 1) return 0.5 * k * k * k * k; 81 | return -0.5 * ((k -= 2) * k * k * k - 2); 82 | } 83 | } 84 | 85 | class Quint extends BaseEasing { 86 | double none(double k) { 87 | return k; 88 | } 89 | 90 | double easeIn(double k) { 91 | return k * k * k * k * k; 92 | } 93 | 94 | double easeOut(double k) { 95 | return --k * k * k * k * k + 1; 96 | } 97 | 98 | double easeInOut(double k) { 99 | if ((k *= 2) < 1) return 0.5 * k * k * k * k * k; 100 | return 0.5 * ((k -= 2) * k * k * k * k + 2); 101 | } 102 | } 103 | 104 | class Sine extends BaseEasing { 105 | double none(double k) { 106 | return k; 107 | } 108 | 109 | double easeIn(double k) { 110 | return 1 - cos(k * pi / 2); 111 | } 112 | 113 | double easeOut(double k) { 114 | return sin(k * pi / 2); 115 | } 116 | 117 | double easeInOut(double k) { 118 | return 0.5 * (1 - cos(pi * k)); 119 | } 120 | } 121 | 122 | class Expo extends BaseEasing { 123 | double none(double k) { 124 | return k; 125 | } 126 | 127 | double easeIn(double k) { 128 | return k == 0 ? 0.0 : pow(1024, k - 1).toDouble(); 129 | } 130 | 131 | double easeOut(double k) { 132 | return k == 1 ? 1 : 1 - pow(2, -10 * k).toDouble(); 133 | } 134 | 135 | double easeInOut(double k) { 136 | if (k == 0) return 0; 137 | if (k == 1) return 1; 138 | if ((k *= 2) < 1) return 0.5 * pow(1024, k - 1); 139 | return 0.5 * (-pow(2, -10 * (k - 1)) + 2); 140 | } 141 | } 142 | 143 | class Circ extends BaseEasing { 144 | double none(double k) { 145 | return k; 146 | } 147 | 148 | double easeIn(double k) { 149 | return 1 - sqrt(1 - k * k); 150 | } 151 | 152 | double easeOut(double k) { 153 | return sqrt(1 - --k * k); 154 | } 155 | 156 | double easeInOut(double k) { 157 | if ((k *= 2) < 1) return -0.5 * (sqrt(1 - k * k) - 1); 158 | return 0.5 * (sqrt(1 - (k -= 2) * k) + 1); 159 | } 160 | } 161 | 162 | class Elastic extends BaseEasing { 163 | double none(double k) { 164 | return k; 165 | } 166 | 167 | double easeIn(double k) { 168 | var s, a = 0.1, p = 0.4; 169 | if (k == 0) return 0; 170 | if (k == 1) return 1; 171 | if (a < 1) { 172 | a = 1; 173 | s = p / 4; 174 | } else 175 | s = p * asin(1 / a) / (2 * pi); 176 | return -(a * pow(2, 10 * (k -= 1)) * sin((k - s) * (2 * pi) / p)); 177 | } 178 | 179 | double easeOut(double k) { 180 | var s, a = 0.1, p = 0.4; 181 | if (k == 0) return 0; 182 | if (k == 1) return 1; 183 | if (a < 1) { 184 | a = 1; 185 | s = p / 4; 186 | } else 187 | s = p * asin(1 / a) / (2 * pi); 188 | return (a * pow(2, -10 * k) * sin((k - s) * (2 * pi) / p) + 1); 189 | } 190 | 191 | double easeInOut(double k) { 192 | var s, a = 0.1, p = 0.4; 193 | if (k == 0) return 0; 194 | if (k == 1) return 1; 195 | if (a < 1) { 196 | a = 1; 197 | s = p / 4; 198 | } else 199 | s = p * asin(1 / a) / (2 * pi); 200 | if ((k *= 2) < 1) 201 | return -0.5 * (a * pow(2, 10 * (k -= 1)) * sin((k - s) * (2 * pi) / p)); 202 | return a * pow(2, -10 * (k -= 1)) * sin((k - s) * (2 * pi) / p) * 0.5 + 1; 203 | } 204 | } 205 | 206 | class Back extends BaseEasing { 207 | double none(double k) { 208 | return k; 209 | } 210 | 211 | double easeIn(double k) { 212 | var s = 1.70158; 213 | return k * k * ((s + 1) * k - s); 214 | } 215 | 216 | double easeOut(double k) { 217 | var s = 1.70158; 218 | return --k * k * ((s + 1) * k + s) + 1; 219 | } 220 | 221 | double easeInOut(double k) { 222 | var s = 1.70158 * 1.525; 223 | if ((k *= 2) < 1) return 0.5 * (k * k * ((s + 1) * k - s)); 224 | return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); 225 | } 226 | } 227 | 228 | class Bounce extends BaseEasing { 229 | double none(double k) { 230 | return k; 231 | } 232 | 233 | double easeIn(double k) { 234 | return 1 - easeOut(1 - k); 235 | } 236 | 237 | double easeOut(double k) { 238 | if (k < (1 / 2.75)) { 239 | return 7.5625 * k * k; 240 | } else if (k < (2 / 2.75)) { 241 | return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; 242 | } else if (k < (2.5 / 2.75)) { 243 | return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; 244 | } else { 245 | return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; 246 | } 247 | } 248 | 249 | double easeInOut(double k) { 250 | if (k < 0.5) return easeIn(k * 2) * 0.5; 251 | return easeOut(k * 2 - 1) * 0.5 + 0.5; 252 | } 253 | } 254 | 255 | class Ease { 256 | static BaseEasing linear = Linear(); 257 | static BaseEasing quad = Quad(); 258 | static BaseEasing cubic = Cubic(); 259 | static BaseEasing quart = Quart(); 260 | static BaseEasing quint = Quint(); 261 | static BaseEasing sine = Sine(); 262 | static BaseEasing expo = Expo(); 263 | static BaseEasing circ = Circ(); 264 | static BaseEasing elastic = Elastic(); 265 | static BaseEasing back = Back(); 266 | static BaseEasing bounce = Bounce(); 267 | } 268 | 269 | class EaseInstanceClass { 270 | BaseEasing linear = Linear(); 271 | BaseEasing quad = Quad(); 272 | BaseEasing cubic = Cubic(); 273 | BaseEasing quart = Quart(); 274 | BaseEasing quint = Quint(); 275 | BaseEasing sine = Sine(); 276 | BaseEasing expo = Expo(); 277 | BaseEasing circ = Circ(); 278 | BaseEasing elastic = Elastic(); 279 | BaseEasing back = Back(); 280 | BaseEasing bounce = Bounce(); 281 | } 282 | -------------------------------------------------------------------------------- /lib/src/miticker.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/scheduler.dart'; 2 | 3 | Ticker? _ticker; 4 | 5 | class Miticker { 6 | static Ticker init(Function func) { 7 | if (_ticker == null) { 8 | _ticker = new Ticker((Duration duration) { 9 | func(duration); 10 | }); 11 | } 12 | 13 | return _ticker!; 14 | } 15 | 16 | static start() { 17 | if (!_ticker!.isActive) { 18 | _ticker!.start(); 19 | } 20 | } 21 | 22 | static stop() { 23 | if (_ticker!.isActive) { 24 | _ticker!.stop(); 25 | } 26 | } 27 | 28 | static Ticker get ticker { 29 | return _ticker!; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/tweener.dart: -------------------------------------------------------------------------------- 1 | import './miticker.dart'; 2 | import './ease.dart'; 3 | 4 | List _tweens = []; 5 | 6 | class Tweener { 7 | static EaseInstanceClass ease = EaseInstanceClass(); 8 | /////////////////////////////////////////////////////////////////////////// 9 | /// 10 | /// Tweener static methods 11 | /// 12 | /////////////////////////////////////////////////////////////////////////// 13 | static List getAll() { 14 | return _tweens; 15 | } 16 | 17 | static void removeAll() { 18 | _tweens = []; 19 | } 20 | 21 | static void add(Tweener tween) { 22 | _tweens.add(tween); 23 | } 24 | 25 | static void remove(Tweener tween) { 26 | var i = _tweens.indexOf(tween); 27 | 28 | if (i != -1) { 29 | _tweens.removeAt(i); 30 | } 31 | } 32 | 33 | static bool _enableManualUpdate = false; 34 | static void enableManualUpdate() { 35 | _enableManualUpdate = true; 36 | } 37 | 38 | static void setup() { 39 | if (_enableManualUpdate) return; 40 | Miticker.init(Tweener._tickerHandler); 41 | Miticker.start(); 42 | } 43 | 44 | static void close() { 45 | Miticker.stop(); 46 | } 47 | 48 | static bool update([time]) { 49 | if (_tweens.length == 0) return false; 50 | 51 | int i = 0, l = _tweens.length; 52 | time = time != null ? time : new DateTime.now().millisecondsSinceEpoch; 53 | 54 | while (i < l) { 55 | if (_tweens[i]._update(time)) { 56 | i++; 57 | } else { 58 | _tweens.removeAt(i); 59 | l--; 60 | } 61 | } 62 | 63 | return true; 64 | } 65 | 66 | static void _tickerHandler(Duration duration) { 67 | Tweener.update(); 68 | } 69 | 70 | /////////////////////////////////////////////////////////////////////////// 71 | /// 72 | /// Tweener class 73 | /// 74 | /////////////////////////////////////////////////////////////////////////// 75 | Map _object = {}; 76 | Map _valuesStart = {}; 77 | Map _valuesEnd = {}; 78 | 79 | int _duration = 0; 80 | int _delayTime = 0; 81 | int _startTime = 0; 82 | 83 | Tweener? _chainedTween; 84 | Function? _easingFunction; 85 | Function? _onUpdateCallback; 86 | Function? _onCompleteCallback; 87 | 88 | Tweener(Map object) { 89 | _object = object; 90 | _valuesStart = {}; 91 | _valuesEnd = {}; 92 | _duration = 1000; 93 | _delayTime = 0; 94 | _easingFunction = Ease.linear.none; 95 | } 96 | 97 | Tweener to(Map properties, [int duration = 1000]) { 98 | _duration = duration; 99 | _valuesEnd = properties; 100 | return this; 101 | } 102 | 103 | Tweener start([time]) { 104 | Tweener.setup(); 105 | Tweener.add(this); 106 | 107 | _startTime = 108 | time != null ? time : new DateTime.now().millisecondsSinceEpoch; 109 | _startTime += _delayTime; 110 | 111 | for (var property in _valuesEnd.keys) { 112 | if (_object[property] == null) { 113 | continue; 114 | } 115 | 116 | _valuesStart[property] = _object[property]; 117 | } 118 | 119 | return this; 120 | } 121 | 122 | Tweener stop() { 123 | Tweener.remove(this); 124 | return this; 125 | } 126 | 127 | Tweener delay(int amount) { 128 | _delayTime = amount; 129 | return this; 130 | } 131 | 132 | Tweener easing(easing) { 133 | _easingFunction = easing; 134 | return this; 135 | } 136 | 137 | Tweener chain(Tweener chainedTween) { 138 | _chainedTween = chainedTween; 139 | return this; 140 | } 141 | 142 | Tweener onUpdate(Function onUpdateCallback) { 143 | _onUpdateCallback = onUpdateCallback; 144 | return this; 145 | } 146 | 147 | Tweener onComplete(Function onCompleteCallback) { 148 | _onCompleteCallback = onCompleteCallback; 149 | return this; 150 | } 151 | 152 | bool _update(int time) { 153 | if (time < _startTime) { 154 | return true; 155 | } 156 | 157 | var elapsed = (time - _startTime) / _duration; 158 | elapsed = elapsed > 1 ? 1 : elapsed; 159 | 160 | var value = _easingFunction!(elapsed); 161 | 162 | for (var property in _valuesStart.keys) { 163 | var start = _valuesStart[property]; 164 | var end = _valuesEnd[property]; 165 | 166 | _object[property] = start + (end - start) * value; 167 | } 168 | 169 | if (_onUpdateCallback != null) { 170 | _onUpdateCallback!(_object); 171 | } 172 | 173 | if (elapsed == 1) { 174 | if (_onCompleteCallback != null) { 175 | _onCompleteCallback!(_object); 176 | } 177 | 178 | if (_chainedTween != null) { 179 | _chainedTween?.start(); 180 | } 181 | 182 | return false; 183 | } 184 | 185 | return true; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /lib/tweener.dart: -------------------------------------------------------------------------------- 1 | library tweener; 2 | 3 | export 'src/tweener.dart'; 4 | export 'src/ease.dart'; 5 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: tweener 2 | description: Tweener is a simple and lightweight flutter animation tool. Anyone can easily learn to use it. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 2.2.3 15 | homepage: https://github.com/flutterkit/tweener 16 | 17 | environment: 18 | sdk: ">=2.12.0 <3.0.0" 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | 24 | # The following adds the Cupertino Icons font to your application. 25 | # Use with the CupertinoIcons class for iOS style icons. 26 | # cupertino_icons: ^0.1.2 27 | 28 | dev_dependencies: 29 | flutter_test: 30 | sdk: flutter 31 | 32 | 33 | # For information on the generic Dart part of this file, see the 34 | # following page: https://www.dartlang.org/tools/pub/pubspec 35 | 36 | # The following section is specific to Flutter. 37 | flutter: 38 | 39 | # The following line ensures that the Material Icons font is 40 | # included with your application, so that you can use the icons in 41 | # the material Icons class. 42 | uses-material-design: true 43 | 44 | # To add assets to your application, add an assets section, like this: 45 | # assets: 46 | # - images/a_dot_burr.jpeg 47 | # - images/a_dot_ham.jpeg 48 | 49 | # An image asset can refer to one or more resolution-specific "variants", see 50 | # https://flutter.dev/assets-and-images/#resolution-aware. 51 | 52 | # For details regarding adding assets from package dependencies, see 53 | # https://flutter.dev/assets-and-images/#from-packages 54 | 55 | # To add custom fonts to your application, add a fonts section here, 56 | # in this "flutter" section. Each entry in this list should have a 57 | # "family" key with the font family name, and a "fonts" key with a 58 | # list giving the asset and other descriptors for the font. For 59 | # example: 60 | # fonts: 61 | # - family: Schyler 62 | # fonts: 63 | # - asset: fonts/Schyler-Regular.ttf 64 | # - asset: fonts/Schyler-Italic.ttf 65 | # style: italic 66 | # - family: Trajan Pro 67 | # fonts: 68 | # - asset: fonts/TrajanPro.ttf 69 | # - asset: fonts/TrajanPro_Bold.ttf 70 | # weight: 700 71 | # 72 | # For details regarding fonts from package dependencies, 73 | # see https://flutter.dev/custom-fonts/#from-packages 74 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | //import 'package:tweener/tweener.dart'; 11 | 12 | void main() { 13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 14 | // Build our app and trigger a frame. 15 | //await tester.pumpWidget(MyApp()); 16 | 17 | // Verify that our counter starts at 0. 18 | expect(find.text('0'), findsOneWidget); 19 | expect(find.text('1'), findsNothing); 20 | 21 | // Tap the '+' icon and trigger a frame. 22 | await tester.tap(find.byIcon(Icons.add)); 23 | await tester.pump(); 24 | 25 | // Verify that our counter has incremented. 26 | expect(find.text('0'), findsNothing); 27 | expect(find.text('1'), findsOneWidget); 28 | }); 29 | } 30 | --------------------------------------------------------------------------------