From 396f7da77f2fa95940a8c3f9418c9bb52e2ea6fe Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Wed, 22 Jul 2015 11:52:34 -0400 Subject: [PATCH 1/3] rebase --- sky/sdk/BUILD.gn | 1 - sky/sdk/example/stocks/lib/stock_home.dart | 37 +++---- sky/sdk/lib/widgets/animation_builder.dart | 115 --------------------- sky/sdk/lib/widgets/drawer.dart | 12 +++ sky/sdk/lib/widgets/snack_bar.dart | 95 ++++++++++++++--- 5 files changed, 106 insertions(+), 154 deletions(-) delete mode 100644 sky/sdk/lib/widgets/animation_builder.dart diff --git a/sky/sdk/BUILD.gn b/sky/sdk/BUILD.gn index 8ee6c835fdc..020af51ead4 100644 --- a/sky/sdk/BUILD.gn +++ b/sky/sdk/BUILD.gn @@ -52,7 +52,6 @@ dart_pkg("sky") { "lib/theme/view_configuration.dart", "lib/widgets/animated_component.dart", "lib/widgets/animated_container.dart", - "lib/widgets/animation_builder.dart", "lib/widgets/basic.dart", "lib/widgets/block_viewport.dart", "lib/widgets/button_base.dart", diff --git a/sky/sdk/example/stocks/lib/stock_home.dart b/sky/sdk/example/stocks/lib/stock_home.dart index 4ce3187ad60..7d8d17a2ca1 100644 --- a/sky/sdk/example/stocks/lib/stock_home.dart +++ b/sky/sdk/example/stocks/lib/stock_home.dart @@ -3,9 +3,6 @@ // found in the LICENSE file. import 'package:sky/editing/input.dart'; -import 'package:sky/animation/animated_value.dart'; -import 'package:sky/widgets/animated_component.dart'; -import 'package:sky/widgets/animation_builder.dart'; import 'package:sky/theme/colors.dart' as colors; import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/drawer.dart'; @@ -35,7 +32,7 @@ typedef void ModeUpdater(StockMode mode); const Duration _kSnackbarSlideDuration = const Duration(milliseconds: 200); -class StockHome extends AnimatedComponent { +class StockHome extends StatefulComponent { StockHome(this.navigator, this.stocks, this.stockMode, this.modeUpdater); @@ -54,7 +51,8 @@ class StockHome extends AnimatedComponent { bool _isSearching = false; String _searchQuery; - AnimationBuilder _snackbarTransform; + SnackBarStatus _snackBarStatus; + bool _isSnackBarShowing = false; // Should it be showing? void _handleSearchBegin() { navigator.pushState(this, (_) { @@ -140,6 +138,7 @@ class StockHome extends AnimatedComponent { Drawer buildDrawer() { if (_drawerStatus == DrawerStatus.inactive) return null; + assert(_drawerShowing); // TODO(mpcomplete): this is always true return new Drawer( level: 3, showing: _drawerShowing, @@ -264,40 +263,34 @@ class StockHome extends AnimatedComponent { void _handleUndo() { setState(() { - _snackbarTransform = null; + _isSnackBarShowing = false; }); } Widget buildSnackBar() { - if (_snackbarTransform == null) + if (_snackBarStatus == SnackBarStatus.inactive) return null; - return _snackbarTransform.build( - new SnackBar( - content: new Text("Stock purchased!"), - actions: [new SnackBarAction(label: "UNDO", onPressed: _handleUndo)] - )); + return new SnackBar( + showing: _isSnackBarShowing, + content: new Text("Stock purchased!"), + actions: [new SnackBarAction(label: "UNDO", onPressed: _handleUndo)], + onStatusChanged: (status) { setState(() { _snackBarStatus = status; }); } + ); } void _handleStockPurchased() { setState(() { - _snackbarTransform = new AnimationBuilder() - ..position = new AnimatedValue(const Point(0.0, 45.0), end: Point.origin); - var performance = _snackbarTransform.createPerformance( - [_snackbarTransform.position], duration: _kSnackbarSlideDuration); - watch(performance); // TODO(mpcomplete): need to unwatch - performance.play(); + _isSnackBarShowing = true; + _snackBarStatus = SnackBarStatus.active; }); } Widget buildFloatingActionButton() { - var widget = new FloatingActionButton( + return new FloatingActionButton( child: new Icon(type: 'content/add', size: 24), backgroundColor: colors.RedAccent[200], onPressed: _handleStockPurchased ); - if (_snackbarTransform != null) - widget = _snackbarTransform.build(widget); - return widget; } void addMenuToOverlays(List overlays) { diff --git a/sky/sdk/lib/widgets/animation_builder.dart b/sky/sdk/lib/widgets/animation_builder.dart deleted file mode 100644 index a0362f3684d..00000000000 --- a/sky/sdk/lib/widgets/animation_builder.dart +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:vector_math/vector_math.dart'; - -import 'package:sky/animation/animated_value.dart'; -import 'package:sky/animation/animation_performance.dart'; -import 'package:sky/painting/box_painter.dart'; -import 'package:sky/theme/shadows.dart'; -import 'package:sky/widgets/basic.dart'; - -// This class builds a Container object from a collection of optionally- -// animated properties. Use syncFields to update the Container's properties, -// which will optionally animate them using an AnimationPerformance. -class AnimationBuilder { - - AnimationBuilder(); - - AnimatedValue opacity; - AnimatedValue position; - AnimatedValue shadow; - AnimatedColor backgroundColor; - - // These don't animate, but are used to build the AnimationBuilder anyway. - double borderRadius; - Shape shape; - - Map _variableToPerformance = - new Map(); - - AnimationPerformance createPerformance(List variables, - { Duration duration }) { - AnimationPerformance performance = new AnimationPerformance() - ..duration = duration - ..variable = new AnimatedList(variables); - for (AnimatedVariable variable in variables) - _variableToPerformance[variable] = performance; - return performance; - } - - Widget build(Widget child) { - Widget current = child; - if (shadow != null || backgroundColor != null || - borderRadius != null || shape != null) { - current = new DecoratedBox( - decoration: new BoxDecoration( - borderRadius: borderRadius, - shape: shape, - boxShadow: shadow != null ? _computeShadow(shadow.value) : null, - backgroundColor: backgroundColor != null ? backgroundColor.value : null), - child: current); - } - - if (position != null) { - Matrix4 transform = new Matrix4.identity(); - transform.translate(position.value.x, position.value.y); - current = new Transform(transform: transform, child: current); - } - - if (opacity != null) { - current = new Opacity(opacity: opacity.value, child: current); - } - - return current; - } - - void updateFields({ - AnimatedValue shadow, - AnimatedColor backgroundColor, - double borderRadius, - Shape shape - }) { - _updateField(this.shadow, shadow); - _updateField(this.backgroundColor, backgroundColor); - this.borderRadius = borderRadius; - this.shape = shape; - } - - void _updateField(AnimatedValue variable, AnimatedValue sourceVariable) { - if (variable == null) - return; // TODO(mpcomplete): Should we handle transition from null? - - AnimationPerformance performance = _variableToPerformance[variable]; - if (performance == null) { - // If there's no performance, no need to animate. - if (sourceVariable != null) - variable.value = sourceVariable.value; - return; - } - - if (variable.value != sourceVariable.value) { - variable - ..begin = variable.value - ..end = sourceVariable.value; - performance - ..progress = 0.0 - ..play(); - } - } -} - -List _computeShadow(double level) { - if (level < 1.0) // shadows[1] is the first shadow - return null; - - int level1 = level.floor(); - int level2 = level.ceil(); - double t = level - level1.toDouble(); - - List shadow = new List(); - for (int i = 0; i < shadows[level1].length; ++i) - shadow.add(lerpBoxShadow(shadows[level1][i], shadows[level2][i], t)); - return shadow; -} diff --git a/sky/sdk/lib/widgets/drawer.dart b/sky/sdk/lib/widgets/drawer.dart index b45aa9f1913..9bb6d211221 100644 --- a/sky/sdk/lib/widgets/drawer.dart +++ b/sky/sdk/lib/widgets/drawer.dart @@ -6,6 +6,8 @@ import 'dart:sky' as sky; import 'package:sky/animation/animated_value.dart'; import 'package:sky/animation/animation_performance.dart'; +import 'package:sky/animation/curves.dart'; +import 'package:sky/base/lerp.dart'; import 'package:sky/theme/shadows.dart'; import 'package:sky/theme/colors.dart' as colors; import 'package:sky/widgets/animated_component.dart'; @@ -44,6 +46,16 @@ enum DrawerStatus { typedef void DrawerStatusChangedCallback(DrawerStatus status); +// TODO(mpcomplete): find a better place for this. +class AnimatedColor extends AnimatedType { + AnimatedColor(Color begin, { Color end, Curve curve: linear }) + : super(begin, end: end, curve: curve); + + void setFraction(double t) { + value = lerpColor(begin, end, t); + } +} + class Drawer extends AnimatedComponent { Drawer({ String key, diff --git a/sky/sdk/lib/widgets/snack_bar.dart b/sky/sdk/lib/widgets/snack_bar.dart index 00455f5f5e0..ada76ebca22 100644 --- a/sky/sdk/lib/widgets/snack_bar.dart +++ b/sky/sdk/lib/widgets/snack_bar.dart @@ -2,13 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:sky/animation/animation_performance.dart'; import 'package:sky/painting/text_style.dart'; import 'package:sky/theme/typography.dart' as typography; +import 'package:sky/widgets/animated_component.dart'; import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/default_text_style.dart'; import 'package:sky/widgets/material.dart'; import 'package:sky/widgets/theme.dart'; +import 'package:vector_math/vector_math.dart'; + +enum SnackBarStatus { + active, + inactive, +} + +typedef void SnackBarStatusChangedCallback(SnackBarStatus status); + +const Duration _kSlideInDuration = const Duration(milliseconds: 200); + class SnackBarAction extends Component { SnackBarAction({String key, this.label, this.onPressed }) : super(key: key) { assert(label != null); @@ -29,18 +42,64 @@ class SnackBarAction extends Component { } } -class SnackBar extends Component { +class SnackBar extends AnimatedComponent { SnackBar({ String key, this.content, - this.actions + this.actions, + this.showing, + this.onStatusChanged }) : super(key: key) { assert(content != null); } - final Widget content; - final List actions; + Widget content; + List actions; + bool showing; + SnackBarStatusChangedCallback onStatusChanged; + + void syncFields(SnackBar source) { + content = source.content; + actions = source.actions; + onStatusChanged = source.onStatusChanged; + if (showing != source.showing) { + showing = source.showing; + showing ? _show() : _hide(); + } + } + + AnimatedType _position; + AnimationPerformance _performance; + + void initState() { + _position = new AnimatedType(new Point(0.0, 50.0), end: Point.origin); + _performance = new AnimationPerformance() + ..duration = _kSlideInDuration + ..variable = _position + ..addListener(_checkStatusChanged); + watch(_performance); + if (showing) + _show(); + } + + void _show() { + _performance.play(); + } + + void _hide() { + _performance.reverse(); + } + + SnackBarStatus _lastStatus; + void _checkStatusChanged() { + SnackBarStatus status = _status; + if (_lastStatus != null && status != _lastStatus && onStatusChanged != null) + onStatusChanged(status); + _lastStatus = status; + } + + SnackBarStatus get _status => _performance.isDismissed ? SnackBarStatus.inactive : SnackBarStatus.active; Widget build() { List children = [ @@ -53,18 +112,22 @@ class SnackBar extends Component { ) ) ) - ]; - if (actions != null) - children.addAll(actions); - return new Material( - level: 2, - color: const Color(0xFF323232), - type: MaterialType.canvas, - child: new Container( - margin: const EdgeDims.symmetric(horizontal: 24.0), - child: new DefaultTextStyle( - style: new TextStyle(color: Theme.of(this).accentColor), - child: new Flex(children) + ]..addAll(actions); + + Matrix4 transform = new Matrix4.identity(); + transform.translate(_position.value.x, _position.value.y); + return new Transform( + transform: transform, + child: new Material( + level: 2, + color: const Color(0xFF323232), + type: MaterialType.canvas, + child: new Container( + margin: const EdgeDims.symmetric(horizontal: 24.0), + child: new DefaultTextStyle( + style: new TextStyle(color: Theme.of(this).accentColor), + child: new Flex(children) + ) ) ) ); From ebbaec976b43f3e6ebf3f8027c2b552e85fe3343 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Thu, 16 Jul 2015 17:23:29 -0700 Subject: [PATCH 2/3] Make SnackBar animate itself. --- sky/sdk/example/stocks/lib/stock_home.dart | 4 ++-- sky/sdk/lib/widgets/drawer.dart | 10 ---------- sky/sdk/lib/widgets/snack_bar.dart | 5 +++-- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/sky/sdk/example/stocks/lib/stock_home.dart b/sky/sdk/example/stocks/lib/stock_home.dart index 7d8d17a2ca1..224ec81fff5 100644 --- a/sky/sdk/example/stocks/lib/stock_home.dart +++ b/sky/sdk/example/stocks/lib/stock_home.dart @@ -51,8 +51,8 @@ class StockHome extends StatefulComponent { bool _isSearching = false; String _searchQuery; - SnackBarStatus _snackBarStatus; - bool _isSnackBarShowing = false; // Should it be showing? + SnackBarStatus _snackBarStatus = SnackBarStatus.inactive; + bool _isSnackBarShowing = false; void _handleSearchBegin() { navigator.pushState(this, (_) { diff --git a/sky/sdk/lib/widgets/drawer.dart b/sky/sdk/lib/widgets/drawer.dart index 9bb6d211221..2b7ecdc7ff0 100644 --- a/sky/sdk/lib/widgets/drawer.dart +++ b/sky/sdk/lib/widgets/drawer.dart @@ -46,16 +46,6 @@ enum DrawerStatus { typedef void DrawerStatusChangedCallback(DrawerStatus status); -// TODO(mpcomplete): find a better place for this. -class AnimatedColor extends AnimatedType { - AnimatedColor(Color begin, { Color end, Curve curve: linear }) - : super(begin, end: end, curve: curve); - - void setFraction(double t) { - value = lerpColor(begin, end, t); - } -} - class Drawer extends AnimatedComponent { Drawer({ String key, diff --git a/sky/sdk/lib/widgets/snack_bar.dart b/sky/sdk/lib/widgets/snack_bar.dart index ada76ebca22..81df1d43a96 100644 --- a/sky/sdk/lib/widgets/snack_bar.dart +++ b/sky/sdk/lib/widgets/snack_bar.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:sky/animation/animated_value.dart'; import 'package:sky/animation/animation_performance.dart'; import 'package:sky/painting/text_style.dart'; import 'package:sky/theme/typography.dart' as typography; @@ -69,11 +70,11 @@ class SnackBar extends AnimatedComponent { } } - AnimatedType _position; + AnimatedValue _position; AnimationPerformance _performance; void initState() { - _position = new AnimatedType(new Point(0.0, 50.0), end: Point.origin); + _position = new AnimatedValue(new Point(0.0, 50.0), end: Point.origin); _performance = new AnimationPerformance() ..duration = _kSlideInDuration ..variable = _position From 69d7ef0e6c5854ffc19dfdbe28239403e3017ed4 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Wed, 22 Jul 2015 11:55:38 -0400 Subject: [PATCH 3/3] Material animates over 200ms --- sky/sdk/lib/widgets/material.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sky/sdk/lib/widgets/material.dart b/sky/sdk/lib/widgets/material.dart index aa44a68b7d0..33d6f8c193f 100644 --- a/sky/sdk/lib/widgets/material.dart +++ b/sky/sdk/lib/widgets/material.dart @@ -49,7 +49,7 @@ class Material extends Component { Widget build() { return new AnimatedContainer( - duration: const Duration(milliseconds: 1000), + duration: const Duration(milliseconds: 200), decoration: new BoxDecoration( backgroundColor: _backgroundColor, borderRadius: edges[type],