mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Make back button control drawer in stocks app
Currently you lose your scroll and drawer state when coming back from the settings pane. I think we should solve this by having the Navigator maintain a Stack and keeping the StockHome alive underneath it. But this is good enough for a first iteration. R=abarth@chromium.org, abarth Review URL: https://codereview.chromium.org/1191153002.
This commit is contained in:
parent
1422bb82aa
commit
d44f8f2dbc
@ -7,29 +7,45 @@ import 'package:sky/widgets/basic.dart';
|
||||
import 'package:sky/widgets/navigator.dart';
|
||||
import 'package:sky/widgets/widget.dart';
|
||||
|
||||
import 'stock_data.dart';
|
||||
import 'stock_home.dart';
|
||||
import 'stock_settings.dart';
|
||||
|
||||
class StocksApp extends App {
|
||||
|
||||
NavigationState _navState = new NavigationState([
|
||||
new Route(name: '/', builder: (navigator) => new StockHome(navigator)),
|
||||
new Route(name: '/settings', builder: (navigator) => new StockSettings(navigator)),
|
||||
]);
|
||||
StocksApp() {
|
||||
_navigationState = new NavigationState([
|
||||
new Route(
|
||||
name: '/',
|
||||
builder: (navigator, route) => new StockHome(navigator, route, _stocks)
|
||||
),
|
||||
new Route(
|
||||
name: '/settings',
|
||||
builder: (navigator, route) => new StockSettings(navigator)
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
void didMount() {
|
||||
new StockDataFetcher((StockData data) {
|
||||
setState(() {
|
||||
data.appendTo(_stocks);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
final List<Stock> _stocks = [];
|
||||
NavigationState _navigationState;
|
||||
|
||||
void onBack() {
|
||||
if (_navState.hasPrevious()) {
|
||||
setState(() {
|
||||
_navState.pop();
|
||||
});
|
||||
return;
|
||||
}
|
||||
print ("Should exit app here");
|
||||
setState(() {
|
||||
_navigationState.pop();
|
||||
});
|
||||
// TODO(jackson): Need a way to invoke default back behavior here
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return new Navigator(_navState);
|
||||
return new Navigator(_navigationState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,19 +29,19 @@ enum StockMode { optimistic, pessimistic }
|
||||
|
||||
class StockHome extends Component {
|
||||
|
||||
StockHome(this._navigator) {
|
||||
StockHome(this.navigator, RouteBase route, this.stocks) : super(stateful: true) {
|
||||
// if (debug)
|
||||
// new Timer(new Duration(seconds: 1), dumpState);
|
||||
new StockDataFetcher((StockData data) {
|
||||
setState(() {
|
||||
data.appendTo(_stocks);
|
||||
});
|
||||
});
|
||||
_drawerController = new DrawerController(_handleDrawerStatusChanged);
|
||||
}
|
||||
|
||||
List<Stock> _stocks = [];
|
||||
Navigator _navigator;
|
||||
void syncFields(StockHome source) {
|
||||
navigator = source.navigator;
|
||||
stocks = source.stocks;
|
||||
}
|
||||
|
||||
Navigator navigator;
|
||||
List<Stock> stocks;
|
||||
|
||||
bool _isSearching = false;
|
||||
String _searchQuery;
|
||||
@ -69,6 +69,9 @@ class StockHome extends Component {
|
||||
bool _drawerShowing = false;
|
||||
|
||||
void _handleDrawerStatusChanged(bool showing) {
|
||||
if (!showing && navigator.currentRoute.name == "/drawer") {
|
||||
navigator.pop();
|
||||
}
|
||||
setState(() {
|
||||
_drawerShowing = showing;
|
||||
});
|
||||
@ -137,7 +140,7 @@ class StockHome extends Component {
|
||||
new MenuDivider(),
|
||||
new MenuItem(
|
||||
icon: 'action/settings',
|
||||
onPressed: () => _navigator.pushNamed('/settings'),
|
||||
onPressed: () => navigator.pushNamed('/settings'),
|
||||
children: [new Text('Settings')]),
|
||||
new MenuItem(
|
||||
icon: 'action/help',
|
||||
@ -146,11 +149,18 @@ class StockHome extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
void _handleOpenDrawer() {
|
||||
_drawerController.open();
|
||||
navigator.pushState("/drawer", (_) {
|
||||
_drawerController.close();
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildToolBar() {
|
||||
return new ToolBar(
|
||||
left: new IconButton(
|
||||
icon: 'navigation/menu_white',
|
||||
onPressed: _drawerController.toggle),
|
||||
onPressed: _handleOpenDrawer),
|
||||
center: new Text('Stocks', style: typography.white.title),
|
||||
right: [
|
||||
new IconButton(
|
||||
@ -194,7 +204,7 @@ class StockHome extends Component {
|
||||
List<Widget> overlays = [
|
||||
new Scaffold(
|
||||
toolbar: _isSearching ? buildSearchBar() : buildToolBar(),
|
||||
body: new Stocklist(stocks: _stocks, query: _searchQuery),
|
||||
body: new Stocklist(stocks: stocks, query: _searchQuery),
|
||||
floatingActionButton: new FloatingActionButton(
|
||||
child: new Icon(type: 'content/add_white', size: 24)
|
||||
),
|
||||
|
||||
@ -4,13 +4,12 @@
|
||||
|
||||
import 'package:sky/widgets/basic.dart';
|
||||
import 'package:sky/widgets/navigator.dart';
|
||||
import 'package:sky/widgets/transition.dart';
|
||||
import 'package:sky/widgets/raised_button.dart';
|
||||
|
||||
List<Route> routes = [
|
||||
new Route(
|
||||
name: 'home',
|
||||
builder: (navigator) => new Container(
|
||||
builder: (navigator, route) => new Container(
|
||||
padding: const EdgeDims.all(20.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFCCCCCC)),
|
||||
child: new Block([
|
||||
@ -28,14 +27,14 @@ List<Route> routes = [
|
||||
),
|
||||
new Route(
|
||||
name: 'shopping',
|
||||
builder: (navigator) => new Container(
|
||||
builder: (navigator, route) => new Container(
|
||||
padding: const EdgeDims.all(20.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFBF5FFF)),
|
||||
child: new Block([
|
||||
new Text("Village Shop"),
|
||||
new RaisedButton(
|
||||
child: new Text('RETURN HOME'),
|
||||
onPressed: () => navigator.back()
|
||||
onPressed: () => navigator.pop()
|
||||
),
|
||||
new RaisedButton(
|
||||
child: new Text('GO TO DUNGEON'),
|
||||
@ -46,7 +45,7 @@ List<Route> routes = [
|
||||
),
|
||||
new Route(
|
||||
name: 'adventure',
|
||||
builder: (navigator) => new Container(
|
||||
builder: (navigator, route) => new Container(
|
||||
padding: const EdgeDims.all(20.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFDC143C)),
|
||||
child: new Block([
|
||||
|
||||
@ -54,9 +54,9 @@ class DrawerController {
|
||||
|
||||
bool get isClosed => position.value == -_kWidth;
|
||||
bool get _isMostlyClosed => position.value <= -_kWidth / 2;
|
||||
void toggle() => _isMostlyClosed ? _open() : _close();
|
||||
void toggle() => _isMostlyClosed ? open() : close();
|
||||
|
||||
void handleMaskTap(_) => _close();
|
||||
void handleMaskTap(_) => close();
|
||||
void handlePointerDown(_) => position.stop();
|
||||
|
||||
void handlePointerMove(sky.PointerEvent event) {
|
||||
@ -75,11 +75,11 @@ class DrawerController {
|
||||
_settle();
|
||||
}
|
||||
|
||||
void _open() => _animateToPosition(0.0);
|
||||
void open() => _animateToPosition(0.0);
|
||||
|
||||
void _close() => _animateToPosition(-_kWidth);
|
||||
void close() => _animateToPosition(-_kWidth);
|
||||
|
||||
void _settle() => _isMostlyClosed ? _close() : _open();
|
||||
void _settle() => _isMostlyClosed ? close() : open();
|
||||
|
||||
void _animateToPosition(double targetPosition) {
|
||||
double distance = (targetPosition - position.value).abs();
|
||||
|
||||
@ -4,18 +4,34 @@
|
||||
|
||||
import 'basic.dart';
|
||||
|
||||
typedef Widget Builder(Navigator navigator);
|
||||
typedef Widget Builder(Navigator navigator, RouteBase route);
|
||||
|
||||
abstract class RouteBase {
|
||||
RouteBase({ this.name });
|
||||
final String name;
|
||||
Widget build(Navigator navigator);
|
||||
Widget build(Navigator navigator, RouteBase route);
|
||||
void popState() { }
|
||||
}
|
||||
|
||||
class Route extends RouteBase {
|
||||
Route({ String name, this.builder }) : super(name: name);
|
||||
final Builder builder;
|
||||
Widget build(Navigator navigator) => builder(navigator);
|
||||
Widget build(Navigator navigator, RouteBase route) => builder(navigator, route);
|
||||
}
|
||||
|
||||
class RouteState extends RouteBase {
|
||||
|
||||
RouteState({this.callback, this.route, String name}) : super(name: name);
|
||||
|
||||
RouteBase route;
|
||||
Function callback;
|
||||
|
||||
Widget build(Navigator navigator, _) => route.build(navigator, this);
|
||||
|
||||
void popState() {
|
||||
if (callback != null)
|
||||
callback(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NavigationState {
|
||||
@ -51,25 +67,16 @@ class NavigationState {
|
||||
|
||||
void pop() {
|
||||
if (historyIndex > 0) {
|
||||
history[historyIndex].popState();
|
||||
history.removeLast();
|
||||
historyIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
void back() {
|
||||
if (historyIndex > 0)
|
||||
historyIndex--;
|
||||
}
|
||||
|
||||
void forward() {
|
||||
historyIndex++;
|
||||
assert(historyIndex < history.length);
|
||||
}
|
||||
}
|
||||
|
||||
class Navigator extends Component {
|
||||
|
||||
Navigator(this.state, { String key }) : super(key: key);
|
||||
Navigator(this.state, { String key }) : super(key: key, stateful: true);
|
||||
|
||||
NavigationState state;
|
||||
|
||||
@ -77,6 +84,17 @@ class Navigator extends Component {
|
||||
state = source.state;
|
||||
}
|
||||
|
||||
RouteBase get currentRoute => state.currentRoute;
|
||||
|
||||
void pushState(String name, Function callback) {
|
||||
RouteBase route = new RouteState(
|
||||
name: name,
|
||||
callback: callback,
|
||||
route: state.currentRoute
|
||||
);
|
||||
push(route);
|
||||
}
|
||||
|
||||
void pushNamed(String name) {
|
||||
setState(() {
|
||||
state.pushNamed(name);
|
||||
@ -95,19 +113,7 @@ class Navigator extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
void back() {
|
||||
setState(() {
|
||||
state.back();
|
||||
});
|
||||
}
|
||||
|
||||
void forward() {
|
||||
setState(() {
|
||||
state.forward();
|
||||
});
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return state.currentRoute.build(this);
|
||||
return state.currentRoute.build(this, state.currentRoute);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user