Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
5b3b3dfb
Commit
5b3b3dfb
authored
Oct 29, 2015
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1862 from abarth/navigator2
Add an initial implementation of Navigator2
parents
90a3a20d
b991b7d6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
375 additions
and
49 deletions
+375
-49
navigation.dart
examples/widgets/navigation.dart
+64
-44
material_app.dart
packages/flutter/lib/src/material/material_app.dart
+18
-5
navigator2.dart
packages/flutter/lib/src/widgets/navigator2.dart
+206
-0
overlay.dart
packages/flutter/lib/src/widgets/overlay.dart
+87
-0
No files found.
examples/widgets/navigation.dart
View file @
5b3b3dfb
...
...
@@ -4,51 +4,71 @@
import
'package:flutter/material.dart'
;
import
'package:flutter/src/widgets/navigator2.dart'
as
n2
;
class
Home
extends
StatelessComponent
{
Widget
build
(
BuildContext
context
)
{
return
new
Container
(
padding:
const
EdgeDims
.
all
(
30.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0xFFCCCCCC
)),
child:
new
Column
(<
Widget
>[
new
Text
(
"You are at home"
),
new
RaisedButton
(
child:
new
Text
(
'GO SHOPPING'
),
onPressed:
()
=>
n2
.
Navigator
.
of
(
context
).
pushNamed
(
'/shopping'
)
),
new
RaisedButton
(
child:
new
Text
(
'START ADVENTURE'
),
onPressed:
()
=>
n2
.
Navigator
.
of
(
context
).
pushNamed
(
'/adventure'
)
)],
justifyContent:
FlexJustifyContent
.
center
)
);
}
}
class
Shopping
extends
StatelessComponent
{
Widget
build
(
BuildContext
context
)
{
return
new
Container
(
padding:
const
EdgeDims
.
all
(
20.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0xFFBF5FFF
)),
child:
new
Column
(<
Widget
>[
new
Text
(
"Village Shop"
),
new
RaisedButton
(
child:
new
Text
(
'RETURN HOME'
),
onPressed:
()
=>
n2
.
Navigator
.
of
(
context
).
pop
()
),
new
RaisedButton
(
child:
new
Text
(
'GO TO DUNGEON'
),
onPressed:
()
=>
n2
.
Navigator
.
of
(
context
).
pushNamed
(
'/adventure'
)
)],
justifyContent:
FlexJustifyContent
.
center
)
);
}
}
class
Adventure
extends
StatelessComponent
{
Widget
build
(
BuildContext
context
)
{
return
new
Container
(
padding:
const
EdgeDims
.
all
(
20.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0xFFDC143C
)),
child:
new
Column
(<
Widget
>[
new
Text
(
"Monster's Lair"
),
new
RaisedButton
(
child:
new
Text
(
'RUN!!!'
),
onPressed:
()
=>
n2
.
Navigator
.
of
(
context
).
pop
()
)],
justifyContent:
FlexJustifyContent
.
center
)
);
}
}
final
Map
<
String
,
RouteBuilder
>
routes
=
<
String
,
RouteBuilder
>{
'/'
:
(
RouteArguments
args
)
=>
new
Container
(
padding:
const
EdgeDims
.
all
(
30.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0xFFCCCCCC
)),
child:
new
Column
(<
Widget
>[
new
Text
(
"You are at home"
),
new
RaisedButton
(
child:
new
Text
(
'GO SHOPPING'
),
onPressed:
()
=>
Navigator
.
of
(
args
.
context
).
pushNamed
(
'/shopping'
)
),
new
RaisedButton
(
child:
new
Text
(
'START ADVENTURE'
),
onPressed:
()
=>
Navigator
.
of
(
args
.
context
).
pushNamed
(
'/adventure'
)
)],
justifyContent:
FlexJustifyContent
.
center
)
),
'/shopping'
:
(
RouteArguments
args
)
=>
new
Container
(
padding:
const
EdgeDims
.
all
(
20.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0xFFBF5FFF
)),
child:
new
Column
(<
Widget
>[
new
Text
(
"Village Shop"
),
new
RaisedButton
(
child:
new
Text
(
'RETURN HOME'
),
onPressed:
()
=>
Navigator
.
of
(
args
.
context
).
pop
()
),
new
RaisedButton
(
child:
new
Text
(
'GO TO DUNGEON'
),
onPressed:
()
=>
Navigator
.
of
(
args
.
context
).
pushNamed
(
'/adventure'
)
)],
justifyContent:
FlexJustifyContent
.
center
)
),
'/adventure'
:
(
RouteArguments
args
)
=>
new
Container
(
padding:
const
EdgeDims
.
all
(
20.0
),
decoration:
new
BoxDecoration
(
backgroundColor:
const
Color
(
0xFFDC143C
)),
child:
new
Column
(<
Widget
>[
new
Text
(
"Monster's Lair"
),
new
RaisedButton
(
child:
new
Text
(
'RUN!!!'
),
onPressed:
()
=>
Navigator
.
of
(
args
.
context
).
pop
()
)],
justifyContent:
FlexJustifyContent
.
center
)
)
'/'
:
(
_
)
=>
new
Home
(),
'/shopping'
:
(
_
)
=>
new
Shopping
(),
'/adventure'
:
(
_
)
=>
new
Adventure
(),
};
final
ThemeData
theme
=
new
ThemeData
(
...
...
packages/flutter/lib/src/material/material_app.dart
View file @
5b3b3dfb
...
...
@@ -8,6 +8,8 @@ import 'package:flutter/rendering.dart';
import
'package:flutter/services.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter/src/widgets/navigator2.dart'
as
n2
;
import
'theme.dart'
;
import
'title.dart'
;
...
...
@@ -31,6 +33,8 @@ AssetBundle _initDefaultBundle() {
final
AssetBundle
_defaultBundle
=
_initDefaultBundle
();
const
bool
_kUseNavigator2
=
false
;
class
MaterialApp
extends
StatefulComponent
{
MaterialApp
({
Key
key
,
...
...
@@ -83,6 +87,19 @@ class _MaterialAppState extends State<MaterialApp> {
void
_metricHandler
(
Size
size
)
=>
setState
(()
{
_size
=
size
;
});
Widget
build
(
BuildContext
context
)
{
Widget
navigator
;
if
(
_kUseNavigator2
)
{
navigator
=
new
n2
.
Navigator
(
key:
_navigator
,
routes:
config
.
routes
);
}
else
{
navigator
=
new
Navigator
(
key:
_navigator
,
routes:
config
.
routes
,
onGenerateRoute:
config
.
onGenerateRoute
);
}
return
new
MediaQuery
(
data:
new
MediaQueryData
(
size:
_size
),
child:
new
Theme
(
...
...
@@ -93,11 +110,7 @@ class _MaterialAppState extends State<MaterialApp> {
bundle:
_defaultBundle
,
child:
new
Title
(
title:
config
.
title
,
child:
new
Navigator
(
key:
_navigator
,
routes:
config
.
routes
,
onGenerateRoute:
config
.
onGenerateRoute
)
child:
navigator
)
)
)
...
...
packages/flutter/lib/src/widgets/navigator2.dart
0 → 100644
View file @
5b3b3dfb
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter/animation.dart'
;
import
'basic.dart'
;
import
'framework.dart'
;
import
'overlay.dart'
;
import
'transitions.dart'
;
abstract
class
Route
{
/// Override this function to return the widget that this route should display.
Widget
createWidget
();
Widget
_child
;
OverlayEntry
_entry
;
void
willPush
()
{
_child
=
createWidget
();
}
void
didPop
(
dynamic
result
)
{
_entry
.
remove
();
}
}
typedef
Widget
RouteBuilder
(
args
);
typedef
RouteBuilder
RouteGenerator
(
String
name
);
const
String
_kDefaultPageName
=
'/'
;
class
Navigator
extends
StatefulComponent
{
Navigator
({
Key
key
,
this
.
routes
,
this
.
onGeneratePage
,
this
.
onUnknownPage
})
:
super
(
key:
key
)
{
// To use a navigator, you must at a minimum define the route with the name '/'.
assert
(
routes
!=
null
);
assert
(
routes
.
containsKey
(
_kDefaultPageName
));
}
final
Map
<
String
,
RouteBuilder
>
routes
;
/// you need to implement this if you pushNamed() to names that might not be in routes.
final
RouteGenerator
onGeneratePage
;
/// 404 generator. You only need to implement this if you have a way to navigate to arbitrary names.
final
RouteBuilder
onUnknownPage
;
static
NavigatorState
of
(
BuildContext
context
)
{
NavigatorState
result
;
context
.
visitAncestorElements
((
Element
element
)
{
if
(
element
is
StatefulComponentElement
&&
element
.
state
is
NavigatorState
)
{
result
=
element
.
state
;
return
false
;
}
return
true
;
});
return
result
;
}
NavigatorState
createState
()
=>
new
NavigatorState
();
}
class
NavigatorState
extends
State
<
Navigator
>
{
GlobalKey
<
OverlayState
>
_overlay
=
new
GlobalKey
<
OverlayState
>();
List
<
Route
>
_history
=
new
List
<
Route
>();
void
initState
()
{
super
.
initState
();
_addRouteToHistory
(
new
PageRoute
(
builder:
config
.
routes
[
_kDefaultPageName
],
name:
_kDefaultPageName
));
}
RouteBuilder
_generatePage
(
String
name
)
{
assert
(
config
.
onGeneratePage
!=
null
);
return
config
.
onGeneratePage
(
name
);
}
bool
get
hasPreviousRoute
=>
_history
.
length
>
1
;
void
pushNamed
(
String
name
,
{
Set
<
Key
>
mostValuableKeys
})
{
final
RouteBuilder
builder
=
config
.
routes
[
name
]
??
_generatePage
(
name
)
??
config
.
onUnknownPage
;
assert
(
builder
!=
null
);
// 404 getting your 404!
push
(
new
PageRoute
(
builder:
builder
,
name:
name
,
mostValuableKeys:
mostValuableKeys
));
}
void
_addRouteToHistory
(
Route
route
)
{
route
.
willPush
();
route
.
_entry
=
new
OverlayEntry
(
child:
route
.
_child
);
_history
.
add
(
route
);
}
void
push
(
Route
route
)
{
OverlayEntry
reference
=
_history
.
last
.
_entry
;
_addRouteToHistory
(
route
);
_overlay
.
currentState
.
insert
(
route
.
_entry
,
above:
reference
);
}
void
pop
([
dynamic
result
])
{
_history
.
removeLast
().
didPop
(
result
);
}
Widget
build
(
BuildContext
context
)
{
return
new
Overlay
(
key:
_overlay
,
initialEntries:
<
OverlayEntry
>[
_history
.
first
.
_entry
]
);
}
}
abstract
class
TransitionRoute
extends
Route
{
PerformanceView
get
performance
=>
_performance
?.
view
;
Performance
_performance
;
Duration
get
transitionDuration
;
Performance
createPerformance
()
{
Duration
duration
=
transitionDuration
;
assert
(
duration
!=
null
&&
duration
>=
Duration
.
ZERO
);
return
new
Performance
(
duration:
duration
,
debugLabel:
debugLabel
);
}
void
willPush
()
{
_performance
=
createPerformance
();
_performance
.
forward
();
super
.
willPush
();
}
Future
didPop
(
dynamic
result
)
async
{
await
_performance
.
reverse
();
super
.
didPop
(
result
);
}
String
get
debugLabel
=>
'
$runtimeType
'
;
String
toString
()
=>
'
$runtimeType
(performance:
$_performance
)'
;
}
class
_Page
extends
StatefulComponent
{
_Page
({
Key
key
,
this
.
route
})
:
super
(
key:
key
);
final
PageRoute
route
;
_PageState
createState
()
=>
new
_PageState
();
}
class
_PageState
extends
State
<
_Page
>
{
final
AnimatedValue
<
Point
>
_position
=
new
AnimatedValue
<
Point
>(
const
Point
(
0.0
,
75.0
),
end:
Point
.
origin
,
curve:
Curves
.
easeOut
);
final
AnimatedValue
<
double
>
_opacity
=
new
AnimatedValue
<
double
>(
0.0
,
end:
1.0
,
curve:
Curves
.
easeOut
);
Widget
build
(
BuildContext
context
)
{
return
new
SlideTransition
(
performance:
config
.
route
.
performance
,
position:
_position
,
child:
new
FadeTransition
(
performance:
config
.
route
.
performance
,
opacity:
_opacity
,
child:
_invokeBuilder
()
)
);
}
Widget
_invokeBuilder
()
{
Widget
result
=
config
.
route
.
builder
(
null
);
assert
(()
{
if
(
result
==
null
)
debugPrint
(
'The builder for route
\'
${config.route.name}
\'
returned null. Route builders must never return null.'
);
assert
(
result
!=
null
&&
'A route builder returned null. See the previous log message for details.'
is
String
);
return
true
;
});
return
result
;
}
}
class
PageRoute
extends
TransitionRoute
{
PageRoute
({
this
.
builder
,
this
.
name
:
'<anonymous>'
,
this
.
mostValuableKeys
})
{
assert
(
builder
!=
null
);
}
final
RouteBuilder
builder
;
final
String
name
;
final
Set
<
Key
>
mostValuableKeys
;
Duration
get
transitionDuration
=>
const
Duration
(
milliseconds:
150
);
Widget
createWidget
()
=>
new
_Page
(
route:
this
);
String
get
debugLabel
=>
'
${super.debugLabel}
(
$name
)'
;
}
packages/flutter/lib/src/widgets/overlay.dart
0 → 100644
View file @
5b3b3dfb
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'basic.dart'
;
import
'framework.dart'
;
class
OverlayEntry
{
OverlayEntry
({
this
.
child
,
bool
opaque:
false
})
:
_opaque
=
opaque
;
final
Widget
child
;
bool
get
opaque
=>
_opaque
;
bool
_opaque
;
void
set
opaque
(
bool
value
)
{
_opaque
=
value
;
_state
?.
setState
(()
{});
}
OverlayState
_state
;
/// Remove the entry from the overlay.
void
remove
()
{
_state
?.
_remove
(
this
);
_state
=
null
;
}
}
class
Overlay
extends
StatefulComponent
{
Overlay
({
Key
key
,
this
.
initialEntries
})
:
super
(
key:
key
);
final
List
<
OverlayEntry
>
initialEntries
;
OverlayState
createState
()
=>
new
OverlayState
();
}
class
OverlayState
extends
State
<
Overlay
>
{
final
List
<
OverlayEntry
>
_entries
=
new
List
<
OverlayEntry
>();
void
initState
()
{
super
.
initState
();
for
(
OverlayEntry
entry
in
config
.
initialEntries
)
insert
(
entry
);
}
void
insert
(
OverlayEntry
entry
,
{
OverlayEntry
above
})
{
assert
(
entry
.
_state
==
null
);
if
(
above
!=
null
)
{
print
(
'above._state
${above._state}
---
${above._state == this}
'
);
print
(
'_entries.contains
${_entries.contains(above)}
'
);
}
assert
(
above
==
null
||
(
above
.
_state
==
this
&&
_entries
.
contains
(
above
)));
entry
.
_state
=
this
;
setState
(()
{
int
index
=
above
==
null
?
_entries
.
length
:
_entries
.
indexOf
(
above
)
+
1
;
_entries
.
insert
(
index
,
entry
);
});
}
void
_remove
(
OverlayEntry
entry
)
{
setState
(()
{
_entries
.
remove
(
entry
);
});
}
Widget
build
(
BuildContext
context
)
{
List
<
Widget
>
backwardsChildren
=
<
Widget
>[];
for
(
int
i
=
_entries
.
length
-
1
;
i
>=
0
;
--
i
)
{
OverlayEntry
entry
=
_entries
[
i
];
backwardsChildren
.
add
(
new
KeyedSubtree
(
key:
new
ObjectKey
(
entry
),
child:
entry
.
child
));
if
(
entry
.
opaque
)
break
;
}
return
new
Stack
(
backwardsChildren
.
reversed
.
toList
(
growable:
false
));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment