AnimationController.fling should respect upper and lower bounds (#4533)
Instead of flinging to between 0.0 and 1.0, we should adapt the default spring to the controller's upper and lower bounds. Fixes #3545
This commit is contained in:
parent
1a3adae101
commit
053df166c4
@ -194,10 +194,10 @@ class AnimationController extends Animation<double>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Flings the timeline with an optional force (defaults to a critically
|
/// Flings the timeline with an optional force (defaults to a critically
|
||||||
/// damped spring) and initial velocity. If velocity is positive, the
|
/// damped spring within [lowerBound] and [upperBound]) and initial velocity.
|
||||||
/// animation will complete, otherwise it will dismiss.
|
/// If velocity is positive, the animation will complete, otherwise it will dismiss.
|
||||||
Future<Null> fling({ double velocity: 1.0, Force force }) {
|
Future<Null> fling({ double velocity: 1.0, Force force }) {
|
||||||
force ??= kDefaultSpringForce;
|
force ??= kDefaultSpringForce.copyWith(left: lowerBound, right: upperBound);
|
||||||
_direction = velocity < 0.0 ? _AnimationDirection.reverse : _AnimationDirection.forward;
|
_direction = velocity < 0.0 ? _AnimationDirection.reverse : _AnimationDirection.forward;
|
||||||
return animateWith(force.release(value, velocity));
|
return animateWith(force.release(value, velocity));
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,19 @@ class SpringForce extends Force {
|
|||||||
/// Where to put the spring's resting point when releasing right.
|
/// Where to put the spring's resting point when releasing right.
|
||||||
final double right;
|
final double right;
|
||||||
|
|
||||||
|
/// Creates a copy of this spring force but with the given fields replaced with the new values.
|
||||||
|
SpringForce copyWith({
|
||||||
|
SpringDescription spring,
|
||||||
|
double left,
|
||||||
|
double right
|
||||||
|
}) {
|
||||||
|
return new SpringForce(
|
||||||
|
spring ?? this.spring,
|
||||||
|
left: left ?? this.left,
|
||||||
|
right: right ?? this.right
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// How pricely to terminate the simulation.
|
/// How pricely to terminate the simulation.
|
||||||
///
|
///
|
||||||
/// We overshoot the target by this distance, but stop the simulation when
|
/// We overshoot the target by this distance, but stop the simulation when
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test("Can set value during status callback", () {
|
test('Can set value during status callback', () {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
AnimationController controller = new AnimationController(
|
AnimationController controller = new AnimationController(
|
||||||
duration: const Duration(milliseconds: 100)
|
duration: const Duration(milliseconds: 100)
|
||||||
@ -39,7 +39,7 @@ void main() {
|
|||||||
controller.stop();
|
controller.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Receives status callbacks for forward and reverse", () {
|
test('Receives status callbacks for forward and reverse', () {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
AnimationController controller = new AnimationController(
|
AnimationController controller = new AnimationController(
|
||||||
duration: const Duration(milliseconds: 100)
|
duration: const Duration(milliseconds: 100)
|
||||||
@ -102,7 +102,7 @@ void main() {
|
|||||||
controller.stop();
|
controller.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Forward and reverse from values", () {
|
test('Forward and reverse from values', () {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
AnimationController controller = new AnimationController(
|
AnimationController controller = new AnimationController(
|
||||||
duration: const Duration(milliseconds: 100)
|
duration: const Duration(milliseconds: 100)
|
||||||
@ -129,4 +129,33 @@ void main() {
|
|||||||
expect(valueLog, equals(<double>[ 0.0 ]));
|
expect(valueLog, equals(<double>[ 0.0 ]));
|
||||||
expect(controller.value, equals(0.0));
|
expect(controller.value, equals(0.0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Can fling to upper and lower bounds', () {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
AnimationController controller = new AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 100)
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.fling();
|
||||||
|
WidgetsBinding.instance.handleBeginFrame(const Duration(seconds: 1));
|
||||||
|
WidgetsBinding.instance.handleBeginFrame(const Duration(seconds: 2));
|
||||||
|
expect(controller.value, 1.0);
|
||||||
|
controller.stop();
|
||||||
|
|
||||||
|
AnimationController largeRangeController = new AnimationController(
|
||||||
|
duration: const Duration(milliseconds: 100),
|
||||||
|
lowerBound: -30.0,
|
||||||
|
upperBound: 45.0
|
||||||
|
);
|
||||||
|
|
||||||
|
largeRangeController.fling();
|
||||||
|
WidgetsBinding.instance.handleBeginFrame(const Duration(seconds: 3));
|
||||||
|
WidgetsBinding.instance.handleBeginFrame(const Duration(seconds: 4));
|
||||||
|
expect(largeRangeController.value, 45.0);
|
||||||
|
largeRangeController.fling(velocity: -1.0);
|
||||||
|
WidgetsBinding.instance.handleBeginFrame(const Duration(seconds: 5));
|
||||||
|
WidgetsBinding.instance.handleBeginFrame(const Duration(seconds: 6));
|
||||||
|
expect(largeRangeController.value, -30.0);
|
||||||
|
largeRangeController.stop();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user