Skip to content

Commit b234fe1

Browse files
committed
Add Animate.value
1 parent 7818581 commit b234fe1

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ MyButton().animate(target: _over ? 1 : 0)
361361
.fade(end: 0.8).scaleXY(end: 1.1)
362362
```
363363

364+
You can also update the `value` property to jump to that position.
364365

365366
Testing Animations
366367
================================================================================

lib/src/animate.dart

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class Animate extends StatefulWidget with AnimateManager<Animate> {
118118
Duration? delay,
119119
this.controller,
120120
this.adapter,
121+
this.value,
121122
this.target,
122123
}) : autoPlay = autoPlay ?? true,
123124
delay = delay ?? Duration.zero {
@@ -134,6 +135,7 @@ class Animate extends StatefulWidget with AnimateManager<Animate> {
134135
warn(autoPlay != false, '$s Animate.autoPlay=false');
135136
warn(adapter == null, '$s Animate.adapter');
136137
warn(target == null, '$s Animate.target');
138+
warn(value == null, '$s Animate.value');
137139
}
138140
_entries = [];
139141
if (effects != null) addEffects(effects);
@@ -193,7 +195,8 @@ class Animate extends StatefulWidget with AnimateManager<Animate> {
193195
final Duration delay;
194196

195197
/// An external [AnimationController] can optionally be specified. By default
196-
/// Animate creates its own controller internally.
198+
/// Animate creates its own controller internally, which can be accessed via
199+
/// [onInit] or [onPlay].
197200
final AnimationController? controller;
198201

199202
/// An [Adapter] can drive the animation from an external source (ex. a [ScrollController],
@@ -216,6 +219,18 @@ class Animate extends StatefulWidget with AnimateManager<Animate> {
216219
/// ```
217220
final double? target;
218221

222+
/// Sets an initial position for the animation between 0 (start) and 1 (end).
223+
/// This corresponds to the `value` of the animation's [controller].
224+
/// When [value] is changed, it will jump to the new position.
225+
///
226+
/// For example, this can be used with [autoPlay]`=false` to display an animation
227+
/// at a specific point (half way through a fade in this case):
228+
///
229+
/// ```
230+
/// foo.animate(value: 0.5, autoPlay: false).fadeIn()
231+
/// ```
232+
final double? value;
233+
219234
late final List<EffectEntry> _entries;
220235
Duration _duration = Duration.zero;
221236
EffectEntry? _lastEntry;
@@ -279,9 +294,8 @@ class _AnimateState extends State<Animate> with SingleTickerProviderStateMixin {
279294
_play();
280295
} else if (oldWidget.adapter != widget.adapter) {
281296
_initAdapter();
282-
} else if (widget.target != oldWidget.target) {
283-
// we don't restart when onPlay changes, because anonymous functions
284-
// can only be compared as strings, which is expensive.
297+
} else if (widget.target != oldWidget.target ||
298+
widget.value != oldWidget.value) {
285299
_play();
286300
}
287301
super.didUpdateWidget(oldWidget);
@@ -296,6 +310,7 @@ class _AnimateState extends State<Animate> with SingleTickerProviderStateMixin {
296310
void _restart() {
297311
_delayed?.ignore();
298312
_initController();
313+
_updateValue();
299314
_delayed = Future.delayed(widget.delay, () => _play());
300315
}
301316

@@ -305,8 +320,8 @@ class _AnimateState extends State<Animate> with SingleTickerProviderStateMixin {
305320

306321
if (widget.controller != null) {
307322
// externally provided AnimationController.
323+
_disposeController();
308324
controller = widget.controller!;
309-
_isInternalController = false;
310325
} else if (!_isInternalController) {
311326
// create a new internal AnimationController.
312327
controller = AnimationController(vsync: this);
@@ -355,15 +370,21 @@ class _AnimateState extends State<Animate> with SingleTickerProviderStateMixin {
355370

356371
void _play() {
357372
_delayed?.ignore(); // for poorly timed hot reloads.
373+
_updateValue();
358374
double? pos = widget.target;
359375
if (pos != null) {
360376
_controller.animateTo(pos);
361377
} else if (widget.autoPlay && _adapter == null) {
362-
_controller.forward(from: 0);
378+
_controller.forward(from: widget.value ?? 0);
363379
widget.onPlay?.call(_controller);
364380
}
365381
}
366382

383+
void _updateValue() {
384+
if (widget.value == null) return;
385+
_controller.value = widget.value!;
386+
}
387+
367388
@override
368389
Widget build(BuildContext context) {
369390
Widget child = widget.child, parent = child;
@@ -390,6 +411,7 @@ extension AnimateWidgetExtensions on Widget {
390411
AnimationController? controller,
391412
Adapter? adapter,
392413
double? target,
414+
double? value,
393415
}) =>
394416
Animate(
395417
key: key,
@@ -402,6 +424,7 @@ extension AnimateWidgetExtensions on Widget {
402424
controller: controller,
403425
adapter: adapter,
404426
target: target,
427+
value: value,
405428
child: this,
406429
);
407430
}

0 commit comments

Comments
 (0)