Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion sky/packages/sky/lib/animation/animation_performance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ class AnimationPerformance {
}

void _tick(double t) {
variable.setProgress(t);
if (variable != null)
variable.setProgress(t);
_notifyListeners();
_checkStatusChanged();
}
Expand Down
50 changes: 25 additions & 25 deletions sky/packages/sky/lib/widgets/drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:sky' as sky;

import 'package:sky/animation/animated_value.dart';
import 'package:sky/animation/animation_performance.dart';
import 'package:sky/animation/forces.dart';
import 'package:sky/theme/shadows.dart';
Expand All @@ -15,6 +16,7 @@ import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/navigator.dart';
import 'package:sky/widgets/scrollable.dart';
import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/transitions.dart';

export 'package:sky/animation/animation_performance.dart' show AnimationStatus;

Expand Down Expand Up @@ -57,17 +59,11 @@ class Drawer extends StatefulComponent {
DrawerStatusChangedCallback onStatusChanged;
Navigator navigator;

SlideInIntention _intention;
ColorTransitionIntention _maskColorIntention;
AnimationPerformance get _performance => _intention.performance;
AnimationPerformance _performance;

void initState() {
_intention = new SlideInIntention(
duration: _kBaseSettleDuration, start: _kClosedPosition, end: _kOpenPosition);
_maskColorIntention = new ColorTransitionIntention(
performance: _intention.performance, start: colors.transparent, end: const Color(0x7F000000));
_performance = new AnimationPerformance(duration: _kBaseSettleDuration);

_performance.addStatusListener(_onStatusChanged);
// Use a spring force for animating the drawer. We can't use curves for
// this because we need a linear curve in order to track the user's finger
// while dragging.
Expand All @@ -87,27 +83,27 @@ class Drawer extends StatefulComponent {

Widget build() {
var mask = new Listener(
child: new AnimatedContainer(
intentions: [_maskColorIntention],
tag: showing
child: new ColorTransition(
performance: _performance,
direction: showing ? Direction.forward : Direction.reverse,
color: new AnimatedColorValue(colors.transparent, end: const Color(0x7F000000))
),
onGestureTap: handleMaskTap
);

Widget content = new AnimatedContainer(
intentions: [
_intention,
// TODO(mpcomplete): it should be easier to override some intentions,
// and have those you don't care about revert to a sensible default.
new ImplicitlySyncDecorationIntention(_kThemeChangeDuration),
new ImplicitlySyncWidthIntention(_kThemeChangeDuration),
],
tag: showing,
decoration: new BoxDecoration(
backgroundColor: Theme.of(this).canvasColor,
boxShadow: shadows[level]),
width: _kWidth,
child: new ScrollableBlock(children)
Widget content = new SlideIn(
performance: _performance,
direction: showing ? Direction.forward : Direction.reverse,
position: new AnimatedValue<Point>(_kClosedPosition, end: _kOpenPosition),
onDismissed: _onDismissed,
child: new AnimatedContainer(
intentions: implicitlySyncFieldsIntention(const Duration(milliseconds: 200)),
decoration: new BoxDecoration(
backgroundColor: Theme.of(this).canvasColor,
boxShadow: shadows[level]),
width: _kWidth,
child: new ScrollableBlock(children)
)
);

return new Listener(
Expand All @@ -120,6 +116,10 @@ class Drawer extends StatefulComponent {
);
}

void _onDismissed() {
_onStatusChanged(AnimationStatus.dismissed);
}

void _onStatusChanged(AnimationStatus status) {
scheduleMicrotask(() {
if (status == AnimationStatus.dismissed &&
Expand Down
86 changes: 25 additions & 61 deletions sky/packages/sky/lib/widgets/navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:sky/animation/forces.dart';
import 'package:sky/widgets/animated_component.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/focus.dart';
import 'package:sky/widgets/transitions.dart';
import 'package:vector_math/vector_math.dart';

typedef Widget RouteBuilder(Navigator navigator, RouteBase route);
Expand Down Expand Up @@ -66,76 +67,39 @@ class RouteState extends RouteBase {
// and support multiple transition types
const Duration _kTransitionDuration = const Duration(milliseconds: 150);
const Point _kTransitionStartPoint = const Point(0.0, 75.0);
class Transition extends AnimatedComponent {
class Transition extends TransitionBase {
Transition({
Key key,
this.content,
this.direction,
this.onDismissed,
this.onCompleted,
Widget child,
Direction direction,
Function onDismissed,
Function onCompleted,
this.interactive
}): super(key: key);
Widget content;
Direction direction;
}): super(key: key,
child: child,
duration: _kTransitionDuration,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted);
bool interactive;
Function onDismissed;
Function onCompleted;

AnimatedValue<Point> _position;
AnimatedValue<double> _opacity;
AnimationPerformance _performance;

void initState() {
_position = new AnimatedValue<Point>(
_kTransitionStartPoint,
end: Point.origin,
curve: easeOut
);
_opacity = new AnimatedValue<double>(0.0, end: 1.0, curve: easeOut);
_performance = new AnimationPerformance(duration: _kTransitionDuration)
..variable = new AnimatedList([_position, _opacity]);
if (direction == Direction.reverse)
_performance.progress = 1.0;
_performance.addStatusListener(_checkStatusChanged);
watch(_performance);
_start();
}

void _start() {
_performance.play(direction);
}

void syncFields(Transition source) {
content = source.content;
interactive = source.interactive;
onDismissed = source.onDismissed;
if (direction != source.direction) {
direction = source.direction;
_start();
}
super.syncFields(source);
}

void _checkStatusChanged(AnimationStatus status) {
if (_performance.isDismissed) {
if (onDismissed != null)
onDismissed();
} else if (_performance.isCompleted) {
if (onCompleted != null)
onCompleted();
}
}

Widget build() {
Matrix4 transform = new Matrix4.identity()
..translate(_position.value.x, _position.value.y);
// TODO(jackson): Hit testing should ignore transform
// TODO(jackson): Block input unless content is interactive
return new Transform(
transform: transform,
child: new Opacity(
opacity: _opacity.value,
child: content
return new SlideIn(
performance: performance,
direction: direction,
position: new AnimatedValue<Point>(_kTransitionStartPoint, end: Point.origin, curve: easeOut),
child: new FadeIn(
performance: performance,
direction: direction,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: easeOut),
child: child
)
);
}
Expand Down Expand Up @@ -233,16 +197,16 @@ class Navigator extends StatefulComponent {
if (i + 1 < state.history.length && state.history[i + 1].fullyOpaque)
continue;
HistoryEntry historyEntry = state.history[i];
Widget content = historyEntry.route.build(this, historyEntry.route);
Widget child = historyEntry.route.build(this, historyEntry.route);
if (i == 0) {
visibleRoutes.add(content);
visibleRoutes.add(child);
continue;
}
if (content == null)
if (child == null)
continue;
Transition transition = new Transition(
key: new Key.fromObjectIdentity(historyEntry),
content: content,
child: child,
direction: (i <= state.historyIndex) ? Direction.forward : Direction.reverse,
interactive: (i == state.historyIndex),
onDismissed: () {
Expand Down
35 changes: 11 additions & 24 deletions sky/packages/sky/lib/widgets/snack_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@

import 'dart:async';

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;
import 'package:sky/widgets/animated_container.dart';
import 'package:sky/widgets/animation_intentions.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:sky/widgets/transitions.dart';

export 'package:sky/animation/animation_performance.dart' show AnimationStatus;

Expand All @@ -39,8 +40,7 @@ class SnackBarAction extends Component {
);
}
}

class SnackBar extends StatefulComponent {
class SnackBar extends Component {

SnackBar({
Key key,
Expand All @@ -57,25 +57,9 @@ class SnackBar extends StatefulComponent {
bool showing;
SnackBarStatusChangedCallback onStatusChanged;

SlideInIntention _intention;

void initState() {
_intention = new SlideInIntention(duration: _kSlideInDuration,
start: const Point(0.0, 50.0),
end: Point.origin);
_intention.performance.addStatusListener(_onStatusChanged);
}

void syncFields(SnackBar source) {
content = source.content;
actions = source.actions;
onStatusChanged = source.onStatusChanged;
showing = source.showing;
}

void _onStatusChanged(AnimationStatus status) {
void _onDismissed() {
if (onStatusChanged != null)
scheduleMicrotask(() { onStatusChanged(status); });
scheduleMicrotask(() { onStatusChanged(AnimationStatus.dismissed); });
}

Widget build() {
Expand All @@ -91,9 +75,12 @@ class SnackBar extends StatefulComponent {
)
]..addAll(actions);

return new AnimatedContainer(
intentions: [_intention],
tag: showing,
return new SlideIn(
duration: _kSlideInDuration,
direction: showing ? Direction.forward : Direction.reverse,
position: new AnimatedValue<Point>(const Point(0.0, 50.0),
end: Point.origin),
onDismissed: _onDismissed,
child: new Material(
level: 2,
color: const Color(0xFF323232),
Expand Down
Loading