Commit 1c06ea17 authored by Collin Jackson's avatar Collin Jackson

Fix #721 Dialogs should appear in place rather than animating in from bottom

parent dda253bb
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
import 'dart:async'; import 'dart:async';
import 'package:sky/animation/animated_value.dart';
import 'package:sky/animation/curves.dart';
import 'package:sky/theme/colors.dart' as colors; import 'package:sky/theme/colors.dart' as colors;
import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/default_text_style.dart'; import 'package:sky/widgets/default_text_style.dart';
...@@ -12,6 +14,7 @@ import 'package:sky/widgets/material.dart'; ...@@ -12,6 +14,7 @@ import 'package:sky/widgets/material.dart';
import 'package:sky/widgets/navigator.dart'; import 'package:sky/widgets/navigator.dart';
import 'package:sky/widgets/scrollable.dart'; import 'package:sky/widgets/scrollable.dart';
import 'package:sky/widgets/theme.dart'; import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/transitions.dart';
typedef Widget DialogBuilder(Navigator navigator); typedef Widget DialogBuilder(Navigator navigator);
...@@ -107,6 +110,47 @@ class Dialog extends Component { ...@@ -107,6 +110,47 @@ class Dialog extends Component {
} }
} }
class DialogRoute extends RouteBase {
DialogRoute({ this.completer, this.builder });
final Completer completer;
final RouteBuilder builder;
Widget build(Navigator navigator, RouteBase route) => builder(navigator, route);
bool get isOpaque => false;
void popState([dynamic result]) {
completer.complete(result);
}
TransitionBase buildTransition({ Key key }) => new DialogTransition(key: key);
}
const Duration _kTransitionDuration = const Duration(milliseconds: 150);
class DialogTransition extends TransitionBase {
DialogTransition({
Key key,
Widget child,
Direction direction,
Function onDismissed,
Function onCompleted
}): super(key: key,
child: child,
duration: _kTransitionDuration,
direction: direction,
onDismissed: onDismissed,
onCompleted: onCompleted);
Widget buildWithChild(Widget child) {
return new FadeTransition(
performance: performance,
direction: direction,
opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: easeOut),
child: child
);
}
}
Future showDialog(Navigator navigator, DialogBuilder builder) { Future showDialog(Navigator navigator, DialogBuilder builder) {
Completer completer = new Completer(); Completer completer = new Completer();
navigator.push(new DialogRoute( navigator.push(new DialogRoute(
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'package:sky/animation/animated_value.dart'; import 'package:sky/animation/animated_value.dart';
import 'package:sky/animation/animation_performance.dart'; import 'package:sky/animation/animation_performance.dart';
import 'package:sky/animation/curves.dart'; import 'package:sky/animation/curves.dart';
...@@ -17,6 +15,7 @@ abstract class RouteBase { ...@@ -17,6 +15,7 @@ abstract class RouteBase {
Widget build(Navigator navigator, RouteBase route); Widget build(Navigator navigator, RouteBase route);
bool get isOpaque; bool get isOpaque;
void popState([dynamic result]) { assert(result == null); } void popState([dynamic result]) { assert(result == null); }
TransitionBase buildTransition({ Key key });
} }
class Route extends RouteBase { class Route extends RouteBase {
...@@ -27,20 +26,7 @@ class Route extends RouteBase { ...@@ -27,20 +26,7 @@ class Route extends RouteBase {
Widget build(Navigator navigator, RouteBase route) => builder(navigator, route); Widget build(Navigator navigator, RouteBase route) => builder(navigator, route);
bool get isOpaque => true; bool get isOpaque => true;
} TransitionBase buildTransition({ Key key }) => new SlideUpFadeTransition(key: key);
class DialogRoute extends RouteBase {
DialogRoute({ this.completer, this.builder });
final Completer completer;
final RouteBuilder builder;
Widget build(Navigator navigator, RouteBase route) => builder(navigator, route);
bool get isOpaque => false;
void popState([dynamic result]) {
completer.complete(result);
}
} }
class RouteState extends RouteBase { class RouteState extends RouteBase {
...@@ -58,32 +44,30 @@ class RouteState extends RouteBase { ...@@ -58,32 +44,30 @@ class RouteState extends RouteBase {
if (callback != null) if (callback != null)
callback(this); callback(this);
} }
TransitionBase buildTransition({ Key key }) {
// Custom state routes shouldn't be asked to construct a transition
assert(false);
return null;
}
} }
// TODO(jackson): Refactor this into its own file // TODO(jackson): Refactor this into its own file
// and support multiple transition types
const Duration _kTransitionDuration = const Duration(milliseconds: 150); const Duration _kTransitionDuration = const Duration(milliseconds: 150);
const Point _kTransitionStartPoint = const Point(0.0, 75.0); const Point _kTransitionStartPoint = const Point(0.0, 75.0);
class Transition extends TransitionBase { class SlideUpFadeTransition extends TransitionBase {
Transition({ SlideUpFadeTransition({
Key key, Key key,
Widget child, Widget child,
Direction direction, Direction direction,
Function onDismissed, Function onDismissed,
Function onCompleted, Function onCompleted
this.interactive
}): super(key: key, }): super(key: key,
child: child, child: child,
duration: _kTransitionDuration, duration: _kTransitionDuration,
direction: direction, direction: direction,
onDismissed: onDismissed, onDismissed: onDismissed,
onCompleted: onCompleted); onCompleted: onCompleted);
bool interactive;
void syncFields(Transition source) {
interactive = source.interactive;
super.syncFields(source);
}
Widget buildWithChild(Widget child) { Widget buildWithChild(Widget child) {
// TODO(jackson): Hit testing should ignore transform // TODO(jackson): Hit testing should ignore transform
...@@ -201,22 +185,19 @@ class Navigator extends StatefulComponent { ...@@ -201,22 +185,19 @@ class Navigator extends StatefulComponent {
} }
if (child == null) if (child == null)
continue; continue;
Transition transition = new Transition( TransitionBase transition = historyEntry.route.buildTransition(key: new Key.fromObjectIdentity(historyEntry))
key: new Key.fromObjectIdentity(historyEntry), ..child = child
child: child, ..direction = (i <= state.historyIndex) ? Direction.forward : Direction.reverse
direction: (i <= state.historyIndex) ? Direction.forward : Direction.reverse, ..onDismissed = () {
interactive: (i == state.historyIndex),
onDismissed: () {
setState(() { setState(() {
state.history.remove(historyEntry); state.history.remove(historyEntry);
}); });
}, }
onCompleted: () { ..onCompleted = () {
setState(() { setState(() {
historyEntry.fullyOpaque = historyEntry.route.isOpaque; historyEntry.fullyOpaque = historyEntry.route.isOpaque;
}); });
} };
);
visibleRoutes.add(transition); visibleRoutes.add(transition);
} }
return new Focus(child: new Stack(visibleRoutes)); return new Focus(child: new Stack(visibleRoutes));
......
...@@ -8,6 +8,8 @@ import 'package:sky/animation/animated_value.dart'; ...@@ -8,6 +8,8 @@ import 'package:sky/animation/animated_value.dart';
import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/basic.dart';
import 'package:vector_math/vector_math.dart'; import 'package:vector_math/vector_math.dart';
export 'package:sky/animation/direction.dart' show Direction;
dynamic _maybe(AnimatedValue x) => x != null ? x.value : null; dynamic _maybe(AnimatedValue x) => x != null ? x.value : null;
// A helper class to anchor widgets to one another. Pass an instance of this to // A helper class to anchor widgets to one another. Pass an instance of this to
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment