提交 79ccfe6b 编写于 作者: C Collin Jackson

Support for settings fly-in animation

上级 c8874f9f
...@@ -10,9 +10,9 @@ List<Route> routes = [ ...@@ -10,9 +10,9 @@ List<Route> routes = [
new Route( new Route(
name: 'home', name: 'home',
builder: (navigator, route) => new Container( builder: (navigator, route) => new Container(
padding: const EdgeDims.all(20.0), padding: const EdgeDims.all(30.0),
decoration: new BoxDecoration(backgroundColor: const Color(0xFFCCCCCC)), decoration: new BoxDecoration(backgroundColor: const Color(0xFFCCCCCC)),
child: new Block([ child: new Flex([
new Text("You are at home"), new Text("You are at home"),
new RaisedButton( new RaisedButton(
child: new Text('GO SHOPPING'), child: new Text('GO SHOPPING'),
...@@ -22,7 +22,7 @@ List<Route> routes = [ ...@@ -22,7 +22,7 @@ List<Route> routes = [
child: new Text('START ADVENTURE'), child: new Text('START ADVENTURE'),
onPressed: () => navigator.pushNamed('adventure') onPressed: () => navigator.pushNamed('adventure')
) )
]) ], direction: FlexDirection.vertical, alignItems: FlexAlignItems.center)
) )
), ),
new Route( new Route(
...@@ -30,7 +30,7 @@ List<Route> routes = [ ...@@ -30,7 +30,7 @@ List<Route> routes = [
builder: (navigator, route) => new Container( builder: (navigator, route) => new Container(
padding: const EdgeDims.all(20.0), padding: const EdgeDims.all(20.0),
decoration: new BoxDecoration(backgroundColor: const Color(0xFFBF5FFF)), decoration: new BoxDecoration(backgroundColor: const Color(0xFFBF5FFF)),
child: new Block([ child: new Flex([
new Text("Village Shop"), new Text("Village Shop"),
new RaisedButton( new RaisedButton(
child: new Text('RETURN HOME'), child: new Text('RETURN HOME'),
...@@ -40,7 +40,7 @@ List<Route> routes = [ ...@@ -40,7 +40,7 @@ List<Route> routes = [
child: new Text('GO TO DUNGEON'), child: new Text('GO TO DUNGEON'),
onPressed: () => navigator.push(routes[2]) onPressed: () => navigator.push(routes[2])
) )
]) ], direction: FlexDirection.vertical)
) )
), ),
new Route( new Route(
...@@ -48,13 +48,13 @@ List<Route> routes = [ ...@@ -48,13 +48,13 @@ List<Route> routes = [
builder: (navigator, route) => new Container( builder: (navigator, route) => new Container(
padding: const EdgeDims.all(20.0), padding: const EdgeDims.all(20.0),
decoration: new BoxDecoration(backgroundColor: const Color(0xFFDC143C)), decoration: new BoxDecoration(backgroundColor: const Color(0xFFDC143C)),
child: new Block([ child: new Flex([
new Text("Monster's Lair"), new Text("Monster's Lair"),
new RaisedButton( new RaisedButton(
child: new Text('NO WAIT! GO BACK!'), child: new Text('NO WAIT! GO BACK!'),
onPressed: () => navigator.pop() onPressed: () => navigator.pop()
) )
]) ], direction: FlexDirection.vertical)
) )
) )
]; ];
......
...@@ -2,7 +2,12 @@ ...@@ -2,7 +2,12 @@
// 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 'package:sky/animation/animation_performance.dart';
import 'package:sky/animation/curves.dart';
import 'package:sky/widgets/animated_component.dart';
import 'package:sky/widgets/animation_builder.dart';
import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/basic.dart';
import 'package:vector_math/vector_math.dart';
typedef Widget Builder(Navigator navigator, RouteBase route); typedef Widget Builder(Navigator navigator, RouteBase route);
...@@ -27,7 +32,7 @@ class RouteState extends RouteBase { ...@@ -27,7 +32,7 @@ class RouteState extends RouteBase {
RouteBase route; RouteBase route;
Function callback; Function callback;
Widget build(Navigator navigator, _) => route.build(navigator, this); Widget build(Navigator navigator, RouteBase route) => null;
void popState() { void popState() {
if (callback != null) if (callback != null)
...@@ -35,6 +40,92 @@ class RouteState extends RouteBase { ...@@ -35,6 +40,92 @@ class RouteState extends RouteBase {
} }
} }
// TODO(jackson): Refactor this into its own file
// and support multiple transition types
const Duration _kTransitionDuration = const Duration(milliseconds: 200);
const Point _kTransitionStartPoint = const Point(0.0, 100.0);
enum TransitionDirection { forward, reverse }
class Transition extends AnimatedComponent {
Transition({ this.content, this.direction, this.onDismissed, this.interactive });
Widget content;
TransitionDirection direction;
bool interactive;
Function onDismissed;
AnimatedType<Point> _position;
AnimatedType<double> _opacity;
AnimationPerformance _performance;
void initState() {
_position = new AnimatedType<Point>(_kTransitionStartPoint)
..end = Point.origin
..curve = easeOut;
_opacity = new AnimatedType<double>(0.0, end: 1.0)
..curve = easeOut;
_performance = new AnimationPerformance()
..duration = _kTransitionDuration
..variable = new AnimatedList([_position, _opacity])
..addListener(_checkDismissed);
if (direction == TransitionDirection.reverse)
_performance.progress = 1.0;
watch(_performance);
_start();
}
void _start() {
_dismissed = false;
switch (direction) {
case TransitionDirection.forward:
_performance.play();
break;
case TransitionDirection.reverse:
_performance.reverse();
break;
}
}
void syncFields(Transition source) {
content = source.content;
if (direction != source.direction) {
direction = source.direction;
_start();
}
onDismissed = source.onDismissed;
super.syncFields(source);
}
bool _dismissed = false;
void _checkDismissed() {
if (!_dismissed &&
direction == TransitionDirection.reverse &&
_performance.isDismissed) {
if (onDismissed != null)
onDismissed();
_dismissed = true;
}
}
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
)
);
}
}
class HistoryEntry {
HistoryEntry(this.route);
final RouteBase route;
// TODO(jackson): Keep track of the requested transition
}
class NavigationState { class NavigationState {
NavigationState(List<Route> routes) { NavigationState(List<Route> routes) {
...@@ -42,16 +133,15 @@ class NavigationState { ...@@ -42,16 +133,15 @@ class NavigationState {
if (route.name != null) if (route.name != null)
namedRoutes[route.name] = route; namedRoutes[route.name] = route;
} }
history.add(routes[0]); history.add(new HistoryEntry(routes[0]));
} }
List<RouteBase> history = new List<RouteBase>(); List<HistoryEntry> history = new List<HistoryEntry>();
int historyIndex = 0; int historyIndex = 0;
Map<String, RouteBase> namedRoutes = new Map<String, RouteBase>(); Map<String, RouteBase> namedRoutes = new Map<String, RouteBase>();
RouteBase get currentRoute => history[historyIndex]; RouteBase get currentRoute => history[historyIndex].route;
bool hasPrevious() => historyIndex > 0; bool hasPrevious() => historyIndex > 0;
bool hasNext() => history.length > historyIndex + 1;
void pushNamed(String name) { void pushNamed(String name) {
Route route = namedRoutes[name]; Route route = namedRoutes[name];
...@@ -60,16 +150,15 @@ class NavigationState { ...@@ -60,16 +150,15 @@ class NavigationState {
} }
void push(RouteBase route) { void push(RouteBase route) {
// Discard future history HistoryEntry historyEntry = new HistoryEntry(route);
history.removeRange(historyIndex + 1, history.length); history.insert(historyIndex + 1, historyEntry);
historyIndex = history.length; historyIndex++;
history.add(route);
} }
void pop() { void pop() {
if (historyIndex > 0) { if (historyIndex > 0) {
history[historyIndex].popState(); HistoryEntry entry = history[historyIndex];
history.removeLast(); entry.route.popState();
historyIndex--; historyIndex--;
} }
} }
...@@ -115,6 +204,26 @@ class Navigator extends StatefulComponent { ...@@ -115,6 +204,26 @@ class Navigator extends StatefulComponent {
} }
Widget build() { Widget build() {
return state.currentRoute.build(this, state.currentRoute); List<Widget> visibleRoutes = new List<Widget>();
for (int i = 0; i < state.history.length; i++) {
HistoryEntry historyEntry = state.history[i];
Widget content = historyEntry.route.build(this, historyEntry.route);
if (i == 0) {
visibleRoutes.add(content);
continue;
}
if (content == null)
continue;
Transition transition = new Transition(content: content)
..direction = (i <= state.historyIndex) ? TransitionDirection.forward : TransitionDirection.reverse
..interactive = (i == state.historyIndex)
..onDismissed = () {
setState(() {
state.history.remove(historyEntry);
});
};
visibleRoutes.add(transition);
}
return new Stack(visibleRoutes);
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册