Skip to content

Commit 9756b59

Browse files
committed
🔧 Update Pack V1 #13
1 parent cf1b7a4 commit 9756b59

14 files changed

+144
-98
lines changed

example/lib/stories/one_shot_animation.dart

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,22 @@ class _OneShotAnimationState extends State<OneShotAnimation> {
1414
return Center(
1515
child: Image.asset('assets/pin_ball_256x.png', width: 150, height: 150)
1616
.fadeIn()
17-
.slideInFromBottom()
17+
.slideInFromLeft()
1818
.blurIn()
19-
.oneShot(
20-
duration: const Duration(milliseconds: 1000),
21-
).then(context).slideOutToLeft().oneShot(),
19+
.oneShot() // child
20+
21+
// Then 1
22+
.slideOutToBottom()
23+
.animateAfter()
24+
25+
// // Then 2
26+
.slideOutToBottom()
27+
.animateAfter()
28+
29+
// // Then 2
30+
.slideOutToBottom()
31+
.animateAfter()
32+
.resetAll()
2233
);
2334
}
2435
}

lib/src/animated_effect.dart

Lines changed: 84 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import 'package:flutter/widgets.dart';
2-
import 'package:hyper_effects/src/apple_curves.dart';
1+
import 'dart:math';
32

4-
import 'effect_animation_value.dart';
3+
import 'package:flutter/widgets.dart';
4+
import 'package:hyper_effects/hyper_effects.dart';
55

66
/// Provides extension methods for [Widget] to animate it's appearance.
77
extension AnimatedEffectExt on Widget {
@@ -40,6 +40,30 @@ extension AnimatedEffectExt on Widget {
4040
);
4141
}
4242

43+
Widget animateAfter({
44+
Duration duration = const Duration(milliseconds: 350),
45+
Curve curve = appleEaseInOut,
46+
int repeat = 0,
47+
bool reverse = false,
48+
Duration delay = Duration.zero,
49+
VoidCallback? onEnd,
50+
}) {
51+
return AnimatedEffect(
52+
shouldTriggerAfterLast: true,
53+
startImmediately: false,
54+
toggle: false,
55+
duration: duration,
56+
curve: curve,
57+
repeat: repeat,
58+
reverse: reverse,
59+
delay: delay,
60+
onEnd: onEnd,
61+
child: this,
62+
);
63+
}
64+
65+
Widget resetAll() => ResetEffect(child: this);
66+
4367
/// Animate the effects applied to this widget.
4468
///
4569
/// Unlike [animate], this method triggers the animation immediately without
@@ -54,7 +78,7 @@ extension AnimatedEffectExt on Widget {
5478
///
5579
/// The [repeat] parameter is used to determine how the animation should be
5680
/// repeated.
57-
Widget oneShot({
81+
AnimatedEffect oneShot({
5882
Duration duration = const Duration(milliseconds: 350),
5983
Curve curve = appleEaseInOut,
6084
int repeat = 0,
@@ -74,40 +98,6 @@ extension AnimatedEffectExt on Widget {
7498
);
7599
}
76100

77-
/// Animates the next effects only after the previous effects have finished.
78-
Widget then(
79-
BuildContext context, {
80-
Duration duration = const Duration(milliseconds: 350),
81-
Curve curve = appleEaseInOut,
82-
int times = 0,
83-
bool reverse = false,
84-
Duration delay = Duration.zero,
85-
}) {
86-
// if (this case AnimatedEffect widget) {
87-
//
88-
// return AnimatedEffect(
89-
// toggle: null,
90-
// duration: duration,
91-
// curve: curve,
92-
// startImmediately: true,
93-
// repeat: times,
94-
// reverse: reverse,
95-
// startAfter: state?._controller,
96-
// child: this,
97-
// );
98-
// }
99-
100-
return AnimatedEffect(
101-
toggle: null,
102-
duration: duration,
103-
curve: curve,
104-
startImmediately: true,
105-
repeat: times,
106-
reverse: reverse,
107-
child: this,
108-
);
109-
}
110-
111101
/// Repeats the chain of preceding effects.
112102
/// [delay] is the delay between each repetition.
113103
/// [repeat] determines how the animation should be repeated.
@@ -162,7 +152,7 @@ class AnimatedEffect extends StatefulWidget {
162152
/// A delay before the animation starts.
163153
final Duration delay;
164154

165-
final AnimationController? startAfter;
155+
final bool shouldTriggerAfterLast;
166156

167157
/// Creates [AnimatedEffect] widget.
168158
const AnimatedEffect({
@@ -176,7 +166,7 @@ class AnimatedEffect extends StatefulWidget {
176166
this.repeat = 0,
177167
this.reverse = false,
178168
this.delay = Duration.zero,
179-
this.startAfter,
169+
this.shouldTriggerAfterLast = false,
180170
});
181171

182172
@override
@@ -206,13 +196,7 @@ class _AnimatedEffectState extends State<AnimatedEffect>
206196

207197
_controller.addStatusListener(onAnimationStatusChanged);
208198

209-
if (widget.startImmediately && widget.startAfter == null) {
210-
forward();
211-
}
212-
213-
if (widget.startAfter != null) {
214-
widget.startAfter!.addStatusListener(startAfterListener);
215-
}
199+
if (widget.startImmediately) forward();
216200
}
217201

218202
@override
@@ -227,7 +211,6 @@ class _AnimatedEffectState extends State<AnimatedEffect>
227211

228212
@override
229213
void dispose() {
230-
widget.startAfter?.removeStatusListener(startAfterListener);
231214
_controller.removeStatusListener(onAnimationStatusChanged);
232215
_controller.dispose();
233216
super.dispose();
@@ -240,15 +223,29 @@ class _AnimatedEffectState extends State<AnimatedEffect>
240223
}
241224

242225
void onAnimationStatusChanged(AnimationStatus status) {
226+
print('onAnimationStatusChanged: $status | ${this.hashCode}');
243227
if (status == AnimationStatus.completed ||
244228
status == AnimationStatus.dismissed) {
245229
widget.onEnd?.call();
246230

247231
if (_repeatTimes == -1 || _repeatTimes > 0) {
248232
if (_repeatTimes != -1 && (!widget.reverse || !shouldReverse)) {
249-
_repeatTimes--;
233+
_repeatTimes = max(0, _repeatTimes - 1);
250234
}
251235
forward();
236+
} else if (_repeatTimes == 0) {
237+
// chaining animations
238+
final parentState =
239+
context.findAncestorStateOfType<_AnimatedEffectState>();
240+
if (parentState?.widget.shouldTriggerAfterLast == true) {
241+
parentState?.forward();
242+
}
243+
if (parentState == null) {
244+
print('resetting from state: ${this.hashCode}');
245+
final resetState =
246+
context.findAncestorStateOfType<_ResetEffectState>();
247+
resetState?.reset();
248+
}
252249
}
253250
}
254251
}
@@ -259,6 +256,7 @@ class _AnimatedEffectState extends State<AnimatedEffect>
259256
if (widget.reverse && shouldReverse) {
260257
_controller.reverse();
261258
} else {
259+
_controller.reset();
262260
_controller.forward(from: 0);
263261
}
264262
shouldReverse = !shouldReverse;
@@ -289,3 +287,40 @@ class _AnimatedEffectState extends State<AnimatedEffect>
289287
);
290288
}
291289
}
290+
291+
class ResetEffect extends StatefulWidget {
292+
final Widget child;
293+
const ResetEffect({super.key, required this.child});
294+
295+
@override
296+
State<ResetEffect> createState() => _ResetEffectState();
297+
}
298+
299+
class _ResetEffectState extends State<ResetEffect> {
300+
@override
301+
Widget build(BuildContext context) => widget.child;
302+
303+
void reset() {
304+
print('reset');
305+
final state = findLeafAnimatedEffectState(context);
306+
print('found state: ${state.hashCode}');
307+
state?.forward();
308+
}
309+
310+
_AnimatedEffectState? findLeafAnimatedEffectState(BuildContext context) {
311+
_AnimatedEffectState? result;
312+
313+
void visitor(Element element) {
314+
final Widget widget = element.widget;
315+
if (widget is AnimatedEffect) {
316+
final StatefulElement editableTextElement = element as StatefulElement;
317+
318+
result = editableTextElement.state as _AnimatedEffectState;
319+
}
320+
element.visitChildren(visitor);
321+
}
322+
323+
context.visitChildElements(visitor);
324+
return result;
325+
}
326+
}

lib/src/effect_builder.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import 'effects/effect.dart';
1414
/// If an animation value is found, the [Effect.lerp] method is called to
1515
/// interpolate between two [Effect]s. The resulting [Effect] is then applied
1616
/// to the [child] by calling [Effect.apply].
17-
class AnimatableEffect extends StatefulWidget {
17+
class EffectWidget extends StatefulWidget {
1818
/// The effect applied to the [child] to interpolate to.
1919
final Effect end;
2020

@@ -24,19 +24,19 @@ class AnimatableEffect extends StatefulWidget {
2424
/// The [Widget] to apply the [end] to.
2525
final Widget child;
2626

27-
/// Creates an [AnimatableEffect].
28-
const AnimatableEffect({
27+
/// Creates an [EffectWidget].
28+
const EffectWidget({
2929
super.key,
3030
this.start,
3131
required this.end,
3232
required this.child,
3333
});
3434

3535
@override
36-
State<AnimatableEffect> createState() => _AnimatableEffectState();
36+
State<EffectWidget> createState() => _EffectWidgetState();
3737
}
3838

39-
class _AnimatableEffectState extends State<AnimatableEffect> {
39+
class _EffectWidgetState extends State<EffectWidget> {
4040
/// The [Effect] to interpolate to.
4141
late Effect end = widget.end;
4242

@@ -62,7 +62,7 @@ class _AnimatableEffectState extends State<AnimatableEffect> {
6262
}
6363

6464
@override
65-
void didUpdateWidget(covariant AnimatableEffect oldWidget) {
65+
void didUpdateWidget(covariant EffectWidget oldWidget) {
6666
super.didUpdateWidget(oldWidget);
6767
if (oldWidget.end != widget.end &&
6868
oldWidget.end.runtimeType == widget.end.runtimeType) {

lib/src/effects/align_effect.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@ import 'effect.dart';
77
extension AlignEffectExt on Widget {
88
/// Applies an [AlignEffect] to a [Widget] with the given [alignment].
99
Widget align(AlignmentGeometry alignment) {
10-
return AnimatableEffect(
10+
return EffectWidget(
1111
end: AlignEffect(alignment: alignment),
1212
child: this,
1313
);
1414
}
1515

1616
/// Applies an [AlignEffect] to a [Widget] only on the x-axis.
1717
Widget alignX(double x) {
18-
return AnimatableEffect(
18+
return EffectWidget(
1919
end: AlignEffect(alignment: Alignment(x, 0)),
2020
child: this,
2121
);
2222
}
2323

2424
/// Applies an [AlignEffect] to a [Widget] only on the y-axis.
2525
Widget alignY(double y) {
26-
return AnimatableEffect(
26+
return EffectWidget(
2727
end: AlignEffect(alignment: Alignment(0, y)),
2828
child: this,
2929
);
@@ -32,7 +32,7 @@ extension AlignEffectExt on Widget {
3232
/// Applies an [AlignEffect] to a [Widget] with the given [x] and [y]
3333
/// values.
3434
Widget alignXY(double x, double y) {
35-
return AnimatableEffect(
35+
return EffectWidget(
3636
end: AlignEffect(
3737
alignment: Alignment(x, y),
3838
),

lib/src/effects/blur_effect.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'effect.dart';
99
extension BlurEffectExt on Widget {
1010
/// Applies a [BlurEffect] to this widget with given [blur] value.
1111
Widget blur(double? blur) {
12-
return AnimatableEffect(
12+
return EffectWidget(
1313
end: BlurEffect(blur: blur),
1414
child: this,
1515
);
@@ -18,7 +18,7 @@ extension BlurEffectExt on Widget {
1818
/// Applies a [BlurEffect] to only the horizontal axis of this widget with
1919
/// given [blurX] value.
2020
Widget blurX(double? blurX) {
21-
return AnimatableEffect(
21+
return EffectWidget(
2222
end: BlurEffect(blurX: blurX),
2323
child: this,
2424
);
@@ -27,7 +27,7 @@ extension BlurEffectExt on Widget {
2727
/// Applies a [BlurEffect] to only the vertical axis of this widget with
2828
/// given [blurY] value.
2929
Widget blurY(double? blurY) {
30-
return AnimatableEffect(
30+
return EffectWidget(
3131
end: BlurEffect(blurY: blurY),
3232
child: this,
3333
);
@@ -36,15 +36,15 @@ extension BlurEffectExt on Widget {
3636
/// Applies a [BlurEffect] to this widget with given [blurX] and [blurY]
3737
/// values.
3838
Widget blurXY(double? blurX, double? blurY) {
39-
return AnimatableEffect(
39+
return EffectWidget(
4040
end: BlurEffect(blurX: blurX, blurY: blurY),
4141
child: this,
4242
);
4343
}
4444

4545
/// Applies a [BlurEffect] to this widget with a default blur in animation.
4646
Widget blurIn({double blur = 10}) {
47-
return AnimatableEffect(
47+
return EffectWidget(
4848
start: BlurEffect(blur: blur),
4949
end: BlurEffect(blur: 0),
5050
child: this,
@@ -53,7 +53,7 @@ extension BlurEffectExt on Widget {
5353

5454
/// Applies a [BlurEffect] to this widget with a default blur out animation.
5555
Widget blurOut({double blur = 10}) {
56-
return AnimatableEffect(
56+
return EffectWidget(
5757
start: BlurEffect(blur: 0),
5858
end: BlurEffect(blur: blur),
5959
child: this,

lib/src/effects/clip_effect.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extension ClipEffectExtension on Widget {
88
double radius = 16,
99
Clip? clip,
1010
]) {
11-
return AnimatableEffect(
11+
return EffectWidget(
1212
end: ClipEffect(
1313
clip: clip ?? Clip.antiAlias,
1414
borderRadius: BorderRadius.circular(radius),
@@ -45,7 +45,7 @@ extension ClipEffectExtension on Widget {
4545
_ => BorderRadius.zero
4646
};
4747

48-
return AnimatableEffect(
48+
return EffectWidget(
4949
end: ClipEffect(
5050
clip: clip ?? Clip.antiAlias,
5151
borderRadius: borderRadius,
@@ -60,7 +60,7 @@ extension ClipEffectExtension on Widget {
6060
BorderRadius borderRadius = const BorderRadius.all(Radius.circular(16)),
6161
Clip? clip,
6262
]) {
63-
return AnimatableEffect(
63+
return EffectWidget(
6464
end: ClipEffect(
6565
clip: clip ?? Clip.antiAlias,
6666
borderRadius: borderRadius,

0 commit comments

Comments
 (0)