mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Port examples to the new animation API
These now use Animation and AnimationController instead of PerformanceView and Performance.
This commit is contained in:
parent
477530f309
commit
fc978c1aa8
@ -12,21 +12,21 @@ final List<String> _iconNames = <String>["event", "home", "android", "alarm", "f
|
||||
class TabViewDemo extends StatelessComponent {
|
||||
Widget _buildTabIndicator(BuildContext context, String iconName) {
|
||||
final Color color = Theme.of(context).primaryColor;
|
||||
final AnimatedColorValue _selectedColor = new AnimatedColorValue(Colors.transparent, end: color, curve: Curves.ease);
|
||||
final AnimatedColorValue _previousColor = new AnimatedColorValue(color, end: Colors.transparent, curve: Curves.ease);
|
||||
final ColorTween _selectedColor = new ColorTween(begin: Colors.transparent, end: color);
|
||||
final ColorTween _previousColor = new ColorTween(begin: color, end: Colors.transparent);
|
||||
final TabBarSelectionState selection = TabBarSelection.of(context);
|
||||
|
||||
return new BuilderTransition(
|
||||
performance: selection.performance,
|
||||
variables: <AnimatedColorValue>[_selectedColor, _previousColor],
|
||||
Animation animation = new CurvedAnimation(parent: selection.animation, curve: Curves.ease);
|
||||
return new AnimationWatchingBuilder(
|
||||
watchable: animation,
|
||||
builder: (BuildContext context) {
|
||||
Color background = selection.value == iconName ? _selectedColor.end : _selectedColor.begin;
|
||||
if (selection.valueIsChanging) {
|
||||
// Then the selection's performance is animating from previousValue to value.
|
||||
if (selection.value == iconName)
|
||||
background = _selectedColor.value;
|
||||
background = _selectedColor.evaluate(animation);
|
||||
else if (selection.previousValue == iconName)
|
||||
background = _previousColor.value;
|
||||
background = _previousColor.evaluate(animation);
|
||||
}
|
||||
return new Container(
|
||||
width: 12.0,
|
||||
|
@ -16,7 +16,7 @@ class _ProgressIndicatorAppState extends State<ProgressIndicatorApp> {
|
||||
duration: const Duration(milliseconds: 1500)
|
||||
)..play(AnimationDirection.forward);
|
||||
|
||||
animation = new ACurve(
|
||||
animation = new CurvedAnimation(
|
||||
parent: controller,
|
||||
curve: new Interval(0.0, 0.9, curve: Curves.ease),
|
||||
reverseCurve: Curves.ease
|
||||
|
@ -26,29 +26,28 @@ class SmoothBlock extends StatefulComponent {
|
||||
class CardTransition extends StatelessComponent {
|
||||
CardTransition({
|
||||
this.child,
|
||||
this.performance,
|
||||
this.animation,
|
||||
this.x,
|
||||
this.opacity,
|
||||
this.scale
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
final Performance performance;
|
||||
final AnimatedValue<double> x;
|
||||
final AnimatedValue<double> opacity;
|
||||
final AnimatedValue<double> scale;
|
||||
final Animation animation;
|
||||
final Evaluatable<double> x;
|
||||
final Evaluatable<double> opacity;
|
||||
final Evaluatable<double> scale;
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return new BuilderTransition(
|
||||
performance: performance,
|
||||
variables: <AnimatedValue<double>>[x, opacity, scale],
|
||||
return new AnimationWatchingBuilder(
|
||||
watchable: animation,
|
||||
builder: (BuildContext context) {
|
||||
double currentScale = scale.evaluate(animation);
|
||||
Matrix4 transform = new Matrix4.identity()
|
||||
..translate(x.value)
|
||||
..scale(scale.value, scale.value);
|
||||
..translate(x.evaluate(animation))
|
||||
..scale(currentScale, currentScale);
|
||||
return new Opacity(
|
||||
opacity: opacity.value,
|
||||
opacity: opacity.evaluate(animation),
|
||||
child: new Transform(
|
||||
transform: transform,
|
||||
child: child
|
||||
@ -63,22 +62,22 @@ class SmoothBlockState extends State<SmoothBlock> {
|
||||
|
||||
double _height = 100.0;
|
||||
|
||||
Widget _handleEnter(PerformanceView performance, Widget child) {
|
||||
Widget _handleEnter(Animation animation, Widget child) {
|
||||
return new CardTransition(
|
||||
x: new AnimatedValue<double>(-200.0, end: 0.0, curve: Curves.ease),
|
||||
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.ease),
|
||||
scale: new AnimatedValue<double>(0.8, end: 1.0, curve: Curves.ease),
|
||||
performance: performance,
|
||||
x: new Tween<double>(begin: -200.0, end: 0.0),
|
||||
opacity: new Tween<double>(begin: 0.0, end: 1.0),
|
||||
scale: new Tween<double>(begin: 0.8, end: 1.0),
|
||||
animation: new CurvedAnimation(parent: animation, curve: Curves.ease),
|
||||
child: child
|
||||
);
|
||||
}
|
||||
|
||||
Widget _handleExit(PerformanceView performance, Widget child) {
|
||||
Widget _handleExit(Animation animation, Widget child) {
|
||||
return new CardTransition(
|
||||
x: new AnimatedValue<double>(0.0, end: 200.0, curve: Curves.ease),
|
||||
opacity: new AnimatedValue<double>(1.0, end: 0.0, curve: Curves.ease),
|
||||
scale: new AnimatedValue<double>(1.0, end: 0.8, curve: Curves.ease),
|
||||
performance: performance,
|
||||
x: new Tween<double>(begin: 0.0, end: 200.0),
|
||||
opacity: new Tween<double>(begin: 1.0, end: 0.0),
|
||||
scale: new Tween<double>(begin: 1.0, end: 0.8),
|
||||
animation: new CurvedAnimation(parent: animation, curve: Curves.ease),
|
||||
child: child
|
||||
);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ abstract class ProxyWatchableMixin implements Watchable {
|
||||
abstract class Evaluatable<T> {
|
||||
const Evaluatable();
|
||||
|
||||
T evaluate(double t);
|
||||
T evaluate(Animation animation);
|
||||
|
||||
WatchableValue<T> watch(Animation parent) {
|
||||
return new WatchableValue<T>(parent: parent, evaluatable: this);
|
||||
@ -105,7 +105,7 @@ class WatchableValue<T> extends Watchable with ProxyWatchableMixin {
|
||||
final Animation parent;
|
||||
final Evaluatable<T> evaluatable;
|
||||
|
||||
T get value => evaluatable.evaluate(parent.progress);
|
||||
T get value => evaluatable.evaluate(parent);
|
||||
}
|
||||
|
||||
abstract class Animation extends Watchable {
|
||||
@ -261,9 +261,8 @@ class _RepeatingSimulation extends Simulation {
|
||||
bool isDone(double timeInSeconds) => false;
|
||||
}
|
||||
|
||||
// TODO(abarth): Rename Curve to UnitTransform and ACurve to Curve.
|
||||
class ACurve extends Animation with ProxyWatchableMixin {
|
||||
ACurve({ this.parent, this.curve, this.reverseCurve }) {
|
||||
class CurvedAnimation extends Animation with ProxyWatchableMixin {
|
||||
CurvedAnimation({ this.parent, this.curve, this.reverseCurve }) {
|
||||
assert(parent != null);
|
||||
assert(curve != null);
|
||||
parent.addStatusListener(_handleStatusChanged);
|
||||
@ -317,9 +316,7 @@ class ACurve extends Animation with ProxyWatchableMixin {
|
||||
}
|
||||
|
||||
class Tween<T extends dynamic> extends Evaluatable<T> {
|
||||
Tween({ this.begin, this.end }) {
|
||||
assert(begin != null);
|
||||
}
|
||||
Tween({ this.begin, this.end });
|
||||
|
||||
/// The value this variable has at the beginning of the animation.
|
||||
T begin;
|
||||
@ -330,9 +327,10 @@ class Tween<T extends dynamic> extends Evaluatable<T> {
|
||||
/// Returns the value this variable has at the given animation clock value.
|
||||
T lerp(double t) => begin + (end - begin) * t;
|
||||
|
||||
T evaluate(double t) {
|
||||
T evaluate(Animation animation) {
|
||||
if (end == null)
|
||||
return begin;
|
||||
double t = animation.progress;
|
||||
if (t == 0.0)
|
||||
return begin;
|
||||
if (t == 1.0)
|
||||
|
@ -415,10 +415,10 @@ class TabBarSelection<T> extends StatefulComponent {
|
||||
|
||||
class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
|
||||
|
||||
PerformanceView get performance => _performance.view;
|
||||
Animation get animation => _controller.view;
|
||||
// Both the TabBar and TabBarView classes access _performance because they
|
||||
// alternately drive selection progress between tabs.
|
||||
final _performance = new Performance(duration: _kTabBarScroll, progress: 1.0);
|
||||
final AnimationController _controller = new AnimationController(duration: _kTabBarScroll, progress: 1.0);
|
||||
final Map<T, int> _valueToIndex = new Map<T, int>();
|
||||
|
||||
void _initValueToIndex() {
|
||||
@ -442,7 +442,7 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_performance.stop();
|
||||
_controller.stop();
|
||||
PageStorage.of(context)?.writeState(context, _value);
|
||||
super.dispose();
|
||||
}
|
||||
@ -481,21 +481,21 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
|
||||
// the previous and current selection index.
|
||||
|
||||
double progress;
|
||||
if (_performance.status == PerformanceStatus.completed)
|
||||
if (_controller.status == PerformanceStatus.completed)
|
||||
progress = 0.0;
|
||||
else if (_previousValue == values.first)
|
||||
progress = _performance.progress;
|
||||
progress = _controller.progress;
|
||||
else if (_previousValue == values.last)
|
||||
progress = 1.0 - _performance.progress;
|
||||
progress = 1.0 - _controller.progress;
|
||||
else if (previousIndex < index)
|
||||
progress = (_performance.progress - 0.5) * 2.0;
|
||||
progress = (_controller.progress - 0.5) * 2.0;
|
||||
else
|
||||
progress = 1.0 - _performance.progress * 2.0;
|
||||
progress = 1.0 - _controller.progress * 2.0;
|
||||
|
||||
_performance
|
||||
_controller
|
||||
..progress = progress
|
||||
..forward().then((_) {
|
||||
if (_performance.progress == 1.0) {
|
||||
if (_controller.progress == 1.0) {
|
||||
if (config.onChanged != null)
|
||||
config.onChanged(_value);
|
||||
_valueIsChanging = false;
|
||||
@ -507,14 +507,14 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
|
||||
|
||||
void registerPerformanceListener(TabBarSelectionPerformanceListener listener) {
|
||||
_performanceListeners.add(listener);
|
||||
_performance
|
||||
_controller
|
||||
..addStatusListener(listener.handleStatusChange)
|
||||
..addListener(listener.handleProgressChange);
|
||||
}
|
||||
|
||||
void unregisterPerformanceListener(TabBarSelectionPerformanceListener listener) {
|
||||
_performanceListeners.remove(listener);
|
||||
_performance
|
||||
_controller
|
||||
..removeStatusListener(listener.handleStatusChange)
|
||||
..removeListener(listener.handleProgressChange);
|
||||
}
|
||||
@ -590,17 +590,11 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
|
||||
|
||||
if (_valueIsChanging && status == PerformanceStatus.completed) {
|
||||
_valueIsChanging = false;
|
||||
double progress = 0.5;
|
||||
if (_selection.index == 0)
|
||||
progress = 0.0;
|
||||
else if (_selection.index == config.labels.length - 1)
|
||||
progress = 1.0;
|
||||
_indicatorTween
|
||||
..begin = _tabIndicatorRect(math.max(0, _selection.index - 1))
|
||||
..end = _tabIndicatorRect(math.min(config.labels.length - 1, _selection.index + 1));
|
||||
setState(() {
|
||||
_indicatorRect
|
||||
..begin = _tabIndicatorRect(math.max(0, _selection.index - 1))
|
||||
..end = _tabIndicatorRect(math.min(config.labels.length - 1, _selection.index + 1))
|
||||
..curve = null
|
||||
..setProgress(progress, AnimationDirection.forward);
|
||||
_indicatorRect = _tabIndicatorRect(_selection.index);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -612,23 +606,32 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
|
||||
if (!_valueIsChanging && _selection.valueIsChanging) {
|
||||
if (config.isScrollable)
|
||||
scrollTo(_centeredTabScrollOffset(_selection.index), duration: _kTabBarScroll);
|
||||
_indicatorRect
|
||||
..begin = _indicatorRect.value ?? _tabIndicatorRect(_selection.previousIndex)
|
||||
..end = _tabIndicatorRect(_selection.index)
|
||||
..curve = Curves.ease;
|
||||
_indicatorTween
|
||||
..begin = _indicatorRect ?? _tabIndicatorRect(_selection.previousIndex)
|
||||
..end = _tabIndicatorRect(_selection.index);
|
||||
_valueIsChanging = true;
|
||||
}
|
||||
Rect oldRect = _indicatorRect.value;
|
||||
_indicatorRect.setProgress(_selection.performance.progress, AnimationDirection.forward);
|
||||
Rect newRect = _indicatorRect.value;
|
||||
if (oldRect != newRect)
|
||||
Rect oldRect = _indicatorRect;
|
||||
double t = _selection.animation.progress;
|
||||
if (_valueIsChanging) {
|
||||
// When _valueIsChanging is true, we're animating based on a ticker and
|
||||
// want to curve the animation. When _valueIsChanging is false, we're
|
||||
// animating based on a pointer event and want linear feedback. It's
|
||||
// possible we should move this curve into the selection animation.
|
||||
t = Curves.ease.transform(t);
|
||||
}
|
||||
// TODO(abarth): If we've never gone through handleStatusChange before, we
|
||||
// might not have set up our _indicatorTween yet.
|
||||
_indicatorRect = _indicatorTween.lerp(t);
|
||||
if (oldRect != _indicatorRect)
|
||||
setState(() { });
|
||||
}
|
||||
|
||||
Size _viewportSize = Size.zero;
|
||||
Size _tabBarSize;
|
||||
List<double> _tabWidths;
|
||||
AnimatedRectValue _indicatorRect = new AnimatedRectValue(null);
|
||||
Rect _indicatorRect;
|
||||
RectTween _indicatorTween = new RectTween();
|
||||
|
||||
Rect _tabRect(int tabIndex) {
|
||||
assert(_tabBarSize != null);
|
||||
@ -673,9 +676,9 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
|
||||
labelColor = isSelectedTab ? selectedColor : color;
|
||||
if (_selection.valueIsChanging) {
|
||||
if (isSelectedTab)
|
||||
labelColor = Color.lerp(color, selectedColor, _selection.performance.progress);
|
||||
labelColor = Color.lerp(color, selectedColor, _selection.animation.progress);
|
||||
else if (isPreviouslySelectedTab)
|
||||
labelColor = Color.lerp(selectedColor, color, _selection.performance.progress);
|
||||
labelColor = Color.lerp(selectedColor, color, _selection.animation.progress);
|
||||
}
|
||||
}
|
||||
return new _Tab(
|
||||
@ -749,7 +752,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
|
||||
children: tabs,
|
||||
selectedIndex: _selection?.index,
|
||||
indicatorColor: indicatorColor,
|
||||
indicatorRect: _indicatorRect.value,
|
||||
indicatorRect: _indicatorRect,
|
||||
textAndIcons: textAndIcons,
|
||||
isScrollable: config.isScrollable,
|
||||
onLayoutChanged: _layoutChanged
|
||||
@ -873,14 +876,14 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
|
||||
return;
|
||||
// The TabBar is driving the TabBarSelection performance.
|
||||
|
||||
final Performance performance = _selection.performance;
|
||||
final Animation animation = _selection.animation;
|
||||
|
||||
if (performance.status == PerformanceStatus.completed) {
|
||||
if (animation.status == PerformanceStatus.completed) {
|
||||
_updateItemsAndScrollBehavior();
|
||||
return;
|
||||
}
|
||||
|
||||
if (performance.status != PerformanceStatus.forward)
|
||||
if (animation.status != PerformanceStatus.forward)
|
||||
return;
|
||||
|
||||
final int selectedIndex = _selection.index;
|
||||
@ -895,9 +898,9 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
|
||||
}
|
||||
|
||||
if (_scrollDirection == AnimationDirection.forward)
|
||||
scrollTo(performance.progress);
|
||||
scrollTo(animation.progress);
|
||||
else
|
||||
scrollTo(1.0 - performance.progress);
|
||||
scrollTo(1.0 - animation.progress);
|
||||
}
|
||||
|
||||
void dispatchOnScroll() {
|
||||
@ -905,12 +908,12 @@ class _TabBarViewState extends PageableListState<TabBarView> implements TabBarSe
|
||||
return;
|
||||
// This class is driving the TabBarSelection's performance.
|
||||
|
||||
final Performance performance = _selection._performance;
|
||||
final AnimationController controller = _selection._controller;
|
||||
|
||||
if (_selection.index == 0 || _selection.index == _tabCount - 1)
|
||||
performance.progress = scrollOffset;
|
||||
controller.progress = scrollOffset;
|
||||
else
|
||||
performance.progress = scrollOffset / 2.0;
|
||||
controller.progress = scrollOffset / 2.0;
|
||||
}
|
||||
|
||||
Future fling(Offset scrollVelocity) {
|
||||
|
@ -70,30 +70,30 @@ class _SmoothlyResizingOverflowBoxState extends State<SmoothlyResizingOverflowBo
|
||||
class _Entry {
|
||||
_Entry({
|
||||
this.child,
|
||||
this.enterPerformance,
|
||||
this.enterController,
|
||||
this.enterTransition
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
final Performance enterPerformance;
|
||||
final AnimationController enterController;
|
||||
final Widget enterTransition;
|
||||
|
||||
Size childSize = Size.zero;
|
||||
|
||||
Performance exitPerformance;
|
||||
AnimationController exitController;
|
||||
Widget exitTransition;
|
||||
|
||||
Widget get currentTransition => exitTransition ?? enterTransition;
|
||||
|
||||
void dispose() {
|
||||
enterPerformance?.stop();
|
||||
exitPerformance?.stop();
|
||||
enterController?.stop();
|
||||
exitController?.stop();
|
||||
}
|
||||
}
|
||||
|
||||
typedef Widget TransitionBuilderCallback(PerformanceView performance, Widget child);
|
||||
typedef Widget TransitionBuilderCallback(Animation animation, Widget child);
|
||||
|
||||
Widget _identityTransition(PerformanceView performance, Widget child) => child;
|
||||
Widget _identityTransition(Animation animation, Widget child) => child;
|
||||
|
||||
class EnterExitTransition extends StatefulComponent {
|
||||
EnterExitTransition({
|
||||
@ -129,11 +129,11 @@ class _EnterExitTransitionState extends State<EnterExitTransition> {
|
||||
}
|
||||
|
||||
_Entry _createEnterTransition() {
|
||||
Performance enterPerformance = new Performance(duration: config.duration)..play();
|
||||
AnimationController enterController = new AnimationController(duration: config.duration)..forward();
|
||||
return new _Entry(
|
||||
child: config.child,
|
||||
enterPerformance: enterPerformance,
|
||||
enterTransition: config.onEnter(enterPerformance, new KeyedSubtree(
|
||||
enterController: enterController,
|
||||
enterTransition: config.onEnter(enterController, new KeyedSubtree(
|
||||
key: new GlobalKey(),
|
||||
child: config.child
|
||||
))
|
||||
@ -141,11 +141,11 @@ class _EnterExitTransitionState extends State<EnterExitTransition> {
|
||||
}
|
||||
|
||||
Future _createExitTransition(_Entry entry) async {
|
||||
Performance exitPerformance = new Performance(duration: config.duration);
|
||||
AnimationController exitController = new AnimationController(duration: config.duration);
|
||||
entry
|
||||
..exitPerformance = exitPerformance
|
||||
..exitTransition = config.onExit(exitPerformance, entry.enterTransition);
|
||||
await exitPerformance.play();
|
||||
..exitController = exitController
|
||||
..exitTransition = config.onExit(exitController, entry.enterTransition);
|
||||
await exitController.forward();
|
||||
if (!mounted)
|
||||
return;
|
||||
setState(() {
|
||||
|
Loading…
Reference in New Issue
Block a user