mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Support for settings fly-in animation
This commit is contained in:
parent
c8874f9f92
commit
79ccfe6b87
@ -10,9 +10,9 @@ List<Route> routes = [
|
||||
new Route(
|
||||
name: 'home',
|
||||
builder: (navigator, route) => new Container(
|
||||
padding: const EdgeDims.all(20.0),
|
||||
padding: const EdgeDims.all(30.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFCCCCCC)),
|
||||
child: new Block([
|
||||
child: new Flex([
|
||||
new Text("You are at home"),
|
||||
new RaisedButton(
|
||||
child: new Text('GO SHOPPING'),
|
||||
@ -22,7 +22,7 @@ List<Route> routes = [
|
||||
child: new Text('START ADVENTURE'),
|
||||
onPressed: () => navigator.pushNamed('adventure')
|
||||
)
|
||||
])
|
||||
], direction: FlexDirection.vertical, alignItems: FlexAlignItems.center)
|
||||
)
|
||||
),
|
||||
new Route(
|
||||
@ -30,7 +30,7 @@ List<Route> routes = [
|
||||
builder: (navigator, route) => new Container(
|
||||
padding: const EdgeDims.all(20.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFBF5FFF)),
|
||||
child: new Block([
|
||||
child: new Flex([
|
||||
new Text("Village Shop"),
|
||||
new RaisedButton(
|
||||
child: new Text('RETURN HOME'),
|
||||
@ -40,7 +40,7 @@ List<Route> routes = [
|
||||
child: new Text('GO TO DUNGEON'),
|
||||
onPressed: () => navigator.push(routes[2])
|
||||
)
|
||||
])
|
||||
], direction: FlexDirection.vertical)
|
||||
)
|
||||
),
|
||||
new Route(
|
||||
@ -48,13 +48,13 @@ List<Route> routes = [
|
||||
builder: (navigator, route) => new Container(
|
||||
padding: const EdgeDims.all(20.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFDC143C)),
|
||||
child: new Block([
|
||||
child: new Flex([
|
||||
new Text("Monster's Lair"),
|
||||
new RaisedButton(
|
||||
child: new Text('NO WAIT! GO BACK!'),
|
||||
onPressed: () => navigator.pop()
|
||||
)
|
||||
])
|
||||
], direction: FlexDirection.vertical)
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
@ -2,7 +2,12 @@
|
||||
// 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/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:vector_math/vector_math.dart';
|
||||
|
||||
typedef Widget Builder(Navigator navigator, RouteBase route);
|
||||
|
||||
@ -27,7 +32,7 @@ class RouteState extends RouteBase {
|
||||
RouteBase route;
|
||||
Function callback;
|
||||
|
||||
Widget build(Navigator navigator, _) => route.build(navigator, this);
|
||||
Widget build(Navigator navigator, RouteBase route) => null;
|
||||
|
||||
void popState() {
|
||||
if (callback != null)
|
||||
@ -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 {
|
||||
|
||||
NavigationState(List<Route> routes) {
|
||||
@ -42,16 +133,15 @@ class NavigationState {
|
||||
if (route.name != null)
|
||||
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;
|
||||
Map<String, RouteBase> namedRoutes = new Map<String, RouteBase>();
|
||||
|
||||
RouteBase get currentRoute => history[historyIndex];
|
||||
RouteBase get currentRoute => history[historyIndex].route;
|
||||
bool hasPrevious() => historyIndex > 0;
|
||||
bool hasNext() => history.length > historyIndex + 1;
|
||||
|
||||
void pushNamed(String name) {
|
||||
Route route = namedRoutes[name];
|
||||
@ -60,16 +150,15 @@ class NavigationState {
|
||||
}
|
||||
|
||||
void push(RouteBase route) {
|
||||
// Discard future history
|
||||
history.removeRange(historyIndex + 1, history.length);
|
||||
historyIndex = history.length;
|
||||
history.add(route);
|
||||
HistoryEntry historyEntry = new HistoryEntry(route);
|
||||
history.insert(historyIndex + 1, historyEntry);
|
||||
historyIndex++;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
if (historyIndex > 0) {
|
||||
history[historyIndex].popState();
|
||||
history.removeLast();
|
||||
HistoryEntry entry = history[historyIndex];
|
||||
entry.route.popState();
|
||||
historyIndex--;
|
||||
}
|
||||
}
|
||||
@ -115,6 +204,26 @@ class Navigator extends StatefulComponent {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user