To create staggered animations, the easiest way is to create one AnimationController that manages all of the animations and to animate them with a CurvedAnimation which takes a parent animation (the animation controller) and a Curve.
Curve Interval Animation
Tags: curve, animation, dart, flutter
The Curve, here, is a special one: the Interval. It allows us define the part of the parent timeline in which the child animation will be animated from beginning to end.
Tween(
begin: Offset(-1.0, 0.0),
end: Offset(0.0, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(.30, .60),
),
),
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Slidable Drawer Delegate Animation
Tags: flutter-layout, flutter, dart
Like all interactive widgets, the complete animation consists of a widget pair: a stateless and a stateful widget. The stateless widget specifies the Tweens, defines the Animation objects, and provides a build() function responsible for building the animating portion of the widget tree. The stateful widget creates the controller, plays the animation, and builds the non-animating portion of the widget tree. The animation begins when a tap is detected anywhere in the screen.
SlidableDrawerDelegateAnimation({
Key key,
this.controller,
}) : dxPositions = >[
Tween(
begin: Offset(-1.0, 0.0),
end: Offset(1.0, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval03,
),
),
Tween(
begin: Offset(-1.0, 0.0),
end: Offset(0.0, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval03,
),
),
Tween(
begin: Offset(0.0, 0.0),
end: Offset(0.5, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval03,
),
),
],
dyPositions1 = List.generate(
_kCount,
(i) => Tween(
begin: Offset.zero,
end: Offset(0.0, -i.toDouble() / 2),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval01,
),
),
),
dyPositions2 = List.generate(
_kCount,
(i) => Tween(
begin: Offset.zero,
end: Offset(0.0, i.toDouble() / 2),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval04,
),
),
),
skewTransform1 = Tween(begin: 0.0, end: 0.5).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval02,
),
),
skewTransform2 = Tween(begin: 0.0, end: -0.5).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval05,
),
),
super(key: key);
final Animation controller;
final List> dyPositions1;
final List> dyPositions2;
final List> dxPositions;
final Animation skewTransform1;
final Animation skewTransform2;
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Const Variables of Animation Intervals
Tags: dart, animation, flutter
The value of the intervals are stored in constants and can be used in an Animated Builder.
const _kAnimInterval01 = const Interval(.00, .30);
const _kAnimInterval02 = const Interval(.00, .30);
const _kAnimInterval03 = const Interval(.30, .60);
const _kAnimInterval04 = const Interval(.60, .90);
const _kAnimInterval05 = const Interval(.60, .90);
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Animated Builder Parent
Tags: builder, animation, controller, dart, flutter
The build() function creates an AnimatedBuilder that takes a builder function (named _buildAnimation() here) and calls it when the animation controller notifies its changes.
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation,
animation: controller,
);
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Build Animation Function
Tags: build, dart, flutter, animation
The buildAnimation() function which does all the heavy work 💪.
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
child: SkewTransition(
skew: skewTransform1,
child: SkewTransition(
skew: skewTransform2,
child: Container(
width: _kActionSize * 4,
height: 256.0,
color: Colors.black87,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildListTile(context, 0),
Stack(
children: List.generate(_kCount, (i) {
return SlideTransition(
position: dyPositions1[i],
child: SlideTransition(
position: dxPositions[i],
child: SlideTransition(
position: dyPositions2[i],
child: _buildWidget(context, i),
),
),
);
}),
),
_buildListTile(context, 2),
],
),
),
),
),
),
);
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Skew Transition Extending Animated Widget
Tags: dart, ios, javascript, transition, skew
The SkewTransition is a custom animated widget which is heavily inspired by the ScaleTransition widget. It’s the widget which controls the skew of the child.
/// Animates the skew of transformed widget.
class SkewTransition extends AnimatedWidget {
/// Creates a skew transition.
///
/// The [skew] argument must not be null.
const SkewTransition({
Key key,
@required Animation skew,
this.child,
}) : super(key: key, listenable: skew);
/// The animation that controls the skew of the child.
Animation get skew => listenable;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final Widget child;
@override
Widget build(BuildContext context) {
final double skewValue = skew.value;
final Matrix4 transform = new Matrix4.skewX(skewValue);
return new Transform(
transform: transform,
child: child,
);
}
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Stateful Widget from Flutter.io Tutorial with SlideTransition
Tags: flutter.io, dart, flutter, widget
The SlideTransition widgets control the positions of the different children. The stateful widget looks a lot like the one you can find in the flutter.io tutorial.
class SlidableDrawerDelegateDemo extends StatefulWidget {
@override
_SlidableDrawerDelegateDemoState createState() =>
new _SlidableDrawerDelegateDemoState();
}
class _SlidableDrawerDelegateDemoState extends State
with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(duration: _kDuration, vsync: this);
}
Future _playAnimation() async {
try {
await _controller.forward().orCancel;
await _controller.reverse().orCancel;
} on TickerCanceled {
// the animation got canceled, probably because we were disposed
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Slidable Drawer Delegate Animation'),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _playAnimation(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SlidableDrawerDelegateAnimation(
controller: _controller.view,
),
),
),
),
);
}
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Code to Run Flutter Animation - Full File
Tags: dart, flash, flutter, actionscript, animation, run
This is all of the code put together to run the example.
import 'dart:async';
import 'package:flutter/material.dart';
const _kDuration = const Duration(milliseconds: 4000);
const _kActionSize = 64.0;
const _kCount = 3;
const _kAnimInterval01 = const Interval(.00, .30);
const _kAnimInterval02 = const Interval(.00, .30);
const _kAnimInterval03 = const Interval(.30, .60);
const _kAnimInterval04 = const Interval(.60, .90);
const _kAnimInterval05 = const Interval(.60, .90);
const archiveAction = const IconSlideAction(
icon: Icons.archive,
color: Colors.blue,
caption: 'Archive',
);
const shareAction = const IconSlideAction(
icon: Icons.share,
color: Colors.indigo,
caption: 'Share',
);
void main() => runApp(
MaterialApp(
home: Material(
child: SlidableDrawerDelegateDemo(),
),
),
);
class SlidableDrawerDelegateDemo extends StatefulWidget {
@override
_SlidableDrawerDelegateDemoState createState() =>
new _SlidableDrawerDelegateDemoState();
}
class _SlidableDrawerDelegateDemoState extends State
with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(duration: _kDuration, vsync: this);
}
Future _playAnimation() async {
try {
await _controller.forward().orCancel;
await _controller.reverse().orCancel;
} on TickerCanceled {
// the animation got canceled, probably because we were disposed
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Slidable Drawer Delegate Animation'),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => _playAnimation(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SlidableDrawerDelegateAnimation(
controller: _controller.view,
),
),
),
),
);
}
}
class SlidableDrawerDelegateAnimation extends StatelessWidget {
SlidableDrawerDelegateAnimation({
Key key,
this.controller,
}) : dxPositions = >[
Tween(
begin: Offset(-1.0, 0.0),
end: Offset(1.0, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval03,
),
),
Tween(
begin: Offset(-1.0, 0.0),
end: Offset(0.0, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval03,
),
),
Tween(
begin: Offset(0.0, 0.0),
end: Offset(0.5, 0.0),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval03,
),
),
],
dyPositions1 = List.generate(
_kCount,
(i) => Tween(
begin: Offset.zero,
end: Offset(0.0, -i.toDouble() / 2),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval01,
),
),
),
dyPositions2 = List.generate(
_kCount,
(i) => Tween(
begin: Offset.zero,
end: Offset(0.0, i.toDouble() / 2),
).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval04,
),
),
),
skewTransform1 = Tween(begin: 0.0, end: 0.5).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval02,
),
),
skewTransform2 = Tween(begin: 0.0, end: -0.5).animate(
CurvedAnimation(
parent: controller,
curve: _kAnimInterval05,
),
),
super(key: key);
final Animation controller;
final List> dyPositions1;
final List> dyPositions2;
final List> dxPositions;
final Animation skewTransform1;
final Animation skewTransform2;
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
child: SkewTransition(
skew: skewTransform1,
child: SkewTransition(
skew: skewTransform2,
child: Container(
width: _kActionSize * 4,
height: 256.0,
color: Colors.black87,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildListTile(context, 0),
Stack(
children: List.generate(_kCount, (i) {
return SlideTransition(
position: dyPositions1[i],
child: SlideTransition(
position: dxPositions[i],
child: SlideTransition(
position: dyPositions2[i],
child: _buildWidget(context, i),
),
),
);
}),
),
_buildListTile(context, 2),
],
),
),
),
),
),
);
}
Widget _buildWidget(BuildContext context, int index) {
switch (index) {
case 0:
return shareAction;
case 1:
return archiveAction;
case 2:
return _buildListTile(context, 1);
}
return null;
}
Widget _buildListTile(BuildContext context, int index) {
return Container(
color: Colors.grey.shade200,
width: _kActionSize * 4,
height: _kActionSize,
child: ListTile(
leading: CircleAvatar(
backgroundColor: Colors.green,
child: Text('\$index'),
foregroundColor: Colors.white,
),
title: Text('Title'),
subtitle: Text('Subtitle'),
),
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation,
animation: controller,
);
}
}
/// Animates the skew of transformed widget.
class SkewTransition extends AnimatedWidget {
/// Creates a skew transition.
///
/// The [skew] argument must not be null.
const SkewTransition({
Key key,
@required Animation skew,
this.child,
}) : super(key: key, listenable: skew);
/// The animation that controls the skew of the child.
Animation get skew => listenable;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final Widget child;
@override
Widget build(BuildContext context) {
final double skewValue = skew.value;
final Matrix4 transform = new Matrix4.skewX(skewValue);
return new Transform(
transform: transform,
child: child,
);
}
}
class IconSlideAction extends StatelessWidget {
/// Creates a slide action with an icon, a [caption] if set and a
/// background color.
///
/// The [closeOnTap] argument must not be null.
const IconSlideAction({
Key key,
@required this.icon,
this.caption,
this.color,
}) : super(key: key);
final IconData icon;
final String caption;
/// The background color.
///
/// Defaults to true.
final Color color;
@override
Widget build(BuildContext context) {
final Color foregroundColor =
ThemeData.estimateBrightnessForColor(color) == Brightness.light
? Colors.black
: Colors.white;
final Text textWidget = new Text(
caption ?? '',
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.primaryTextTheme
.caption
.copyWith(color: foregroundColor),
);
return Container(
color: color,
width: _kActionSize,
height: _kActionSize,
child: new Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
new Flexible(
child: new Icon(
icon,
color: foregroundColor,
),
),
new Flexible(child: textWidget),
],
),
),
);
}
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Build Animation: Changed Interval and Total Duration
Tags: flutter-layout, dart, flutter
For this simpler animation, we have to keep only one SlideTransition, removes the slide actions, and change the interval and total duration.
const _kDuration = const Duration(milliseconds: 2000);
const _kAnimInterval03 = const Interval(.00, .90);
...
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
child: Container(
width: _kActionSize * 4,
height: 256.0,
color: Colors.black87,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildListTile(context, 0),
SlideTransition(
position: dxPositions[2],
child: _buildWidget(context, 2),
),
_buildListTile(context, 2),
],
),
),
),
);
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html
Single SlideTransition Animation with Inverse
Tags: flutter-layout, dart, flutter, animation
For this animation, we have to keep only one SlideTransition, modify the cross axis alignment, inverse the order of the children, and change the interval and total duration.
const _kDuration = const Duration(milliseconds: 2000);
const _kAnimInterval03 = const Interval(.00, .90);
...
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
child: Container(
width: _kActionSize * 4,
height: 256.0,
color: Colors.black87,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildListTile(context, 0),
SlideTransition(
position: dxPositions[2],
child: _buildWidget(context, 2),
),
_buildListTile(context, 2),
],
),
),
),
);
}
Related links:
- https://docs.flutter.io/flutter/widgets/ScaleTransition-class.html
- https://flutter.io/animations/staggered-animations/
- https://flutter.io/animations/staggered-animations/#complete-staggered-animation
- https://www.screentogif.com/?l=fr_fr
- https://docs.flutter.io/flutter/widgets/SlideTransition-class.html
- https://medium.com/flutter-community/create-simple-animations-for-your-articles-with-flutter-7769085108d1
- https://github.com/letsar/flutter_slidable
- https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html