Well-designed animations improve the user experience by making a UI feel more intuitive. They also contribute to the smooth appearance and feel of a professional product.
In this article, I will show you five animation packages you can use in your next Flutter application.
The SpinKit package contains a set of animated loading indicators for use in your projects.
Pub link: https://pub.dev/packages/flutter_spinkit
Github: https://github.com/jogboms/flutter_spinkit
dependencies:
flutter_spinkit: “<latest_version>”
To build complex animation from available Spinkit predefined widgets
To animate any widget by adding the widget as a child of any Spinkit predefined widget
Can be used in a StatelessWidget or StatefulWidget
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
void main() {
runApp(SpinKitDemo());
}
class SpinKitDemo extends StatelessWidget {
final _loading = ValueNotifier(false);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SpinKit Demo',
theme: ThemeData(
primarySwatch: Colors.red,
),
home: Scaffold(
body: Center(
child: ValueListenableBuilder(
valueListenable: _loading,
builder: (BuildContext context, bool value, Widget child) {
if (value) {
return SpinKitFadingCircle(
color: Colors.red,
size: 50.0,
);
} else {
return ElevatedButton(
onPressed: () async {
try {
_loading.value = true;
await Future.delayed(const Duration(seconds: 5));
} finally {
_loading.value = false;
}
},
child: Text('Login'));
}
},
),
),
),
);
}
}
These are official pre-canned animations for commonly-used effects. You can tweak the animations with your content and place them into your app to amuse your users.
Material motion is a set of transition patterns that assist users to understand and navigate an app. It now supports four different transition patterns.
The following transition patterns are defined by material motion:
Container transform
Shared axis
Fade through
Fade
Pub link: https://pub.dev/packages/animations
Github: https://github.com/flutter/packages/tree/master/packages/animations
dependencies:
animations: “<latest_version>”
To include smooth transition patterns that help the user navigate your apps
To include motion animation in your application according to material design motion specifications
To improve the user experience of your application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import 'package:animations/animations.dart';
import 'package:flutter/material.dart';
void main() {
runApp(AnimationsDemo());
}
class AnimationsDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animations Demo',
theme: ThemeData(
primarySwatch: Colors.red,
),
home: ContainerTransformDemo(),
);
}
}
class ContainerTransformDemo extends StatefulWidget {
const ContainerTransformDemo({
Key key
}): super(key: key);
@override
_ContainerTransformDemoState createState() {
return _ContainerTransformDemoState();
}
}
class _ContainerTransformDemoState extends State < ContainerTransformDemo > {
ContainerTransitionType _transitionType = ContainerTransitionType.fade;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Container transform demo'),
),
body: ListView(
padding: const EdgeInsets.all(8.0),
children: <Widget>[
...List<Widget>.generate(10, (int index) {
return OpenContainer<bool>(
transitionType: _transitionType,
openBuilder: (BuildContext _, VoidCallback openContainer) {
return _DemoDetailsPage();
},
closedShape: const RoundedRectangleBorder(),
closedElevation: 0.0,
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return ListTile(
onTap: openContainer,
title: Text('Title item {index + 1}'),
subtitle: const Text('subtitle text'),
);
},
);
}),
],
),
);
}
}
class _DemoDetailsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Demo details page'),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Title',
style: Theme.of(context).textTheme.headline5.copyWith(
color: Colors.black54,
fontSize: 30.0,
),
),
const SizedBox(height: 10),
Text(
'Demo details page',
style: Theme.of(context).textTheme.bodyText2.copyWith(
color: Colors.black54,
height: 1.5,
fontSize: 16.0,
),
),
],
),
),
],
),
);
}
}
Simple Animations is a strong animation package that allows you to quickly build beautiful bespoke animations.
Pub link: https://pub.dev/packages/simple_animations
Github: https://github.com/felixblaschke/simple_animations
dependencies:
simple_animations: “<latest_version>”
Create custom animations using stateless widgets
Animate multiple properties using TimelineTwin
Doesn’t need an elaborate setup of animation controller and ticker provider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import 'package:flutter/material.dart';
import 'package:simple_animations/simple_animations.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(child: SimpleAnimationDemo(), ),
),
));
}
class SimpleAnimationDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PlayAnimation < double > (
tween: Tween(begin: 0.0, end: 200),
duration: const Duration(seconds: 2),
curve: Curves.ease,
builder: (context, child, value) {
return Container(
width: value,
height: value,
color: Colors.red,
);
},
);
}
}
A useful animation package for adding staggered animations to your ListView, GridView, Column, and Row children per Material Design principles.
Pub link: https://pub.dev/packages/flutter_staggered_animations
Github link: https://github.com/mobiten/flutter_staggered_animations
dependencies:
flutter_staggered_animations: “<latest_version>”
To show animated list view, grid view, or column
To improve the user experience of your application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
mport 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(child: StaggeredAnimationDemo(), ),
),
));
}
class StaggeredAnimationDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: AnimationLimiter(
child: ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(seconds: 1),
child: SlideAnimation(
verticalOffset: 44.0,
child: FadeInAnimation(
child: Card(
child: ListTile(
title: Text('$index item'),
),
),
),
),
);
},
),
),
),
);
}
}
A simple and powerful pre-built animation kit for creating apps quickly and easily. You can use it to add intriguing motion effects to your widgets, such as pop, shake, and flip. These animations can be utilized to improve usability in your apps if applied correctly.
Pub link: https://pub.dev/packages/spring
Github link: https://github.com/KaushickSArgekar/spring
dependencies:
spring: “<latest_version>”
Get a lot of pre-built animation for common use cases
To animate any widget by adding the widget as a child of any Spring pre-built widgets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import 'package:flutter/material.dart';
import 'package:spring/spring.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('SpringDemo'),
),
body: Center(
child: SpringDemo(),
),
),
));
}
class SpringDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Spring.scale(start: 0.2, end: 1.0, child: _RedCard()),
Spring.slide(slideType: SlideType.slide_in_left, child: _RedCard()),
Spring.shake(child: _RedCard()),
Spring.rotate(child: _RedCard()),
],
);
}
}
class _RedCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 60,
width: 60,
decoration: BoxDecoration(
color: Colors.red, borderRadius: BorderRadius.circular(6)),
);
}
}