montage
a organize animations widgets for flutter
quickstart
// 1. define your animations
const entrance = montageanimation(
key: 'entrance',
duration: duration(seconds: 2),
);
const exit = montageanimation(
key: 'exit',
duration: duration(seconds: 2),
);
class home extends statefulwidget {
const home({
key? key,
}) : super(key: key);
@override
_homestate createstate() => _homestate();
}
class _homestate extends state<home> with tickerproviderstatemixin {
montagecontroller? controller;
@override
void initstate() {
controller = montagecontroller(
vsync: this,
initialanimation: entrance,
);
super.initstate();
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: valuelistenablebuilder<montageanimation?>(
valuelistenable: controller!.current,
builder: (context, current, child) => text(current?.key ?? 'none'),
),
),
// 2. wrap your animated widget in a `montage` with its controller.
body: montage(
controller: controller!,
child: basicscene(),
),
floatingactionbutton: floatingactionbutton.extended(
onpressed: () {
/// plays this sequence of animations
controller!.play([
entrance,
exit,
]);
},
label: text('play'),
icon: icon(icons.video_call),
),
);
}
}
class basicscene extends statelesswidget {
const basicscene({
key? key,
}) : super(key: key);
@override
widget build(buildcontext context) {
return column(
mainaxissize: mainaxissize.min,
crossaxisalignment: crossaxisalignment.center,
children: [
// 3. use the motion widgets that defiens motions for each one of your animations
motion(
motion: {
// you can use the provider motions or custom ones
entrance: motions.combine([
motions.rotate(startturns: -1, endturns: 0),
motions.fadein,
]),
exit: motions.combine([
motions.rotate(startturns: 0, endturns: 1),
motions.fadeout,
]),
},
child: flutterlogo(
size: 50,
),
),
motiontext(
text: 'hello world',
style: textstyle(
fontsize: 64,
color: colors.black,
fontweight: fontweight.bold,
),
charactermotion: {
entrance: motions.fadefromtop(),
exit: motions.fadetotop(),
},
reversedcharacteranimation: [exit],
wordmotion: {
entrance: motions.fadein,
exit: motions.fadeout,
},
),
],
);
}
}
widgets
declaring animation references
you must start by declaring you scene’s various animation sequences as montageanimation
global objects.
const entrance = montageanimation(
duration: duration(seconds: 2),
);
const idle = montageanimation(
duration: duration(seconds: 3),
);
const exit = montageanimation(
duration: duration(seconds: 2),
);
montage
the montage serves as the root configuration for your motion widgets. it takes a dedicated controller that will allow to trigger animations.
class _homestate extends state<home> with tickerproviderstatemixin {
montagecontroller? controller;
@override
void initstate() {
controller = montagecontroller(
vsync: this,
initialanimation: entrance,
);
super.initstate();
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
widget build(buildcontext context) {
return scaffold(
body: montage(
controller: controller!,
child: scene(),
),
floatingactionbutton: floatingactionbutton(
icon: icon(icons.video_call),
onpressed: () {
/// plays this sequence of animations
controller!.play([
entrance,
exit,
entrance,
idle,
exit,
]);
},
),
);
}
}
motion
the core widget that can animate a child widget
differently for each one of the played motionanimation
from the root montage
‘s controller.
motion(
motion: {
entrance: motions.fadein,
exit: motions.fadeout,
},
child: flutterlogo(
size: 50,
),
)
staggered animation
if you want to animated a set of widgets progressively, you use the motion.staggered
helper method.
two curves are provided with children animated in the original order as forward
, or children animated in reverse order with backwards
.
you can also configure overlap
if you want that animation of each children starts before the end of the previous one.
row(
mainaxissize: mainaxissize.min,
crossaxisalignment: crossaxisalignment.start,
children: [
...motion.staggered(
children: [
text("fl"),
text("ut"),
text("ter"),
],
motion: (child, i, forward, backward) {
return {
entrance: motions.curved(
forward,
motions.combine([
motions.rotate(startturns: -1, endturns: 0),
motions.fadein,
motions.scale(begin: 3, end: 1)
]),
),
exit: motions.curved(
backward,
motions.combine([
motions.rotate(startturns: 0, endturns: -1),
motions.fadeout,
motions.scale(begin: 1, end: 3)
]),
),
};
},
)
],
),
motions
built-in
a set of motions is available from the motions.dart
file.
custom
a motion is just a widget builder from the current animation<double>
and the child widget
that should be animated.
widget fadein(
buildcontext context,
montageanimation current,
animation<double> animation,
widget? child,
) {
return fadetransition(
opacity: animation,
child: child,
);
}
Comments are closed.