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
f23c9ae5
Unverified
Commit
f23c9ae5
authored
Aug 28, 2018
by
xster
Committed by
GitHub
Aug 28, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cupertino nav bar transitions between routes (#20322)
parent
05b4bd74
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2827 additions
and
342 deletions
+2827
-342
cupertino_refresh_demo.dart
...er_gallery/lib/demo/cupertino/cupertino_refresh_demo.dart
+5
-1
app.dart
packages/flutter/lib/src/cupertino/app.dart
+1
-7
nav_bar.dart
packages/flutter/lib/src/cupertino/nav_bar.dart
+1510
-267
tab_view.dart
packages/flutter/lib/src/cupertino/tab_view.dart
+40
-11
heroes.dart
packages/flutter/lib/src/widgets/heroes.dart
+155
-44
implicit_animations.dart
packages/flutter/lib/src/widgets/implicit_animations.dart
+18
-0
sliver_persistent_header.dart
...ges/flutter/lib/src/widgets/sliver_persistent_header.dart
+1
-0
transitions.dart
packages/flutter/lib/src/widgets/transitions.dart
+59
-0
nav_bar_test.dart
packages/flutter/test/cupertino/nav_bar_test.dart
+67
-9
nav_bar_transition_test.dart
packages/flutter/test/cupertino/nav_bar_transition_test.dart
+811
-0
route_test.dart
packages/flutter/test/cupertino/route_test.dart
+66
-0
scaffold_test.dart
packages/flutter/test/cupertino/scaffold_test.dart
+3
-3
heroes_test.dart
packages/flutter/test/widgets/heroes_test.dart
+91
-0
No files found.
examples/flutter_gallery/lib/demo/cupertino/cupertino_refresh_demo.dart
View file @
f23c9ae5
...
...
@@ -55,7 +55,11 @@ class _CupertinoRefreshControlDemoState extends State<CupertinoRefreshControlDem
new
CupertinoSliverRefreshControl
(
onRefresh:
()
{
return
new
Future
<
void
>.
delayed
(
const
Duration
(
seconds:
2
))
..
then
((
_
)
=>
setState
(()
=>
repopulateList
()));
..
then
((
_
)
{
if
(
mounted
)
{
setState
(()
=>
repopulateList
());
}
});
},
),
new
SliverSafeArea
(
...
...
packages/flutter/lib/src/cupertino/app.dart
View file @
f23c9ae5
...
...
@@ -320,13 +320,10 @@ class _AlwaysCupertinoScrollBehavior extends ScrollBehavior {
}
class
_CupertinoAppState
extends
State
<
CupertinoApp
>
{
HeroController
_heroController
;
List
<
NavigatorObserver
>
_navigatorObservers
;
@override
void
initState
()
{
super
.
initState
();
_heroController
=
new
HeroController
();
// Linear tweening.
_updateNavigator
();
}
...
...
@@ -342,9 +339,6 @@ class _CupertinoAppState extends State<CupertinoApp> {
widget
.
routes
.
isNotEmpty
||
widget
.
onGenerateRoute
!=
null
||
widget
.
onUnknownRoute
!=
null
;
_navigatorObservers
=
new
List
<
NavigatorObserver
>.
from
(
widget
.
navigatorObservers
)
..
add
(
_heroController
);
}
Widget
defaultBuilder
(
BuildContext
context
,
Widget
child
)
{
...
...
@@ -361,7 +355,7 @@ class _CupertinoAppState extends State<CupertinoApp> {
routes:
widget
.
routes
,
onGenerateRoute:
widget
.
onGenerateRoute
,
onUnknownRoute:
widget
.
onUnknownRoute
,
navigatorObservers:
_
navigatorObservers
,
navigatorObservers:
widget
.
navigatorObservers
,
);
if
(
widget
.
builder
!=
null
)
{
return
widget
.
builder
(
context
,
navigator
);
...
...
packages/flutter/lib/src/cupertino/nav_bar.dart
View file @
f23c9ae5
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/cupertino/tab_view.dart
View file @
f23c9ae5
...
...
@@ -37,7 +37,7 @@ import 'route.dart';
/// * [CupertinoTabScaffold], a typical host that supports switching between tabs.
/// * [CupertinoPageRoute], a typical modal page route pushed onto the
/// [CupertinoTabView]'s [Navigator].
class
CupertinoTabView
extends
State
less
Widget
{
class
CupertinoTabView
extends
State
ful
Widget
{
/// Creates the content area for a tab in a [CupertinoTabScaffold].
const
CupertinoTabView
({
Key
key
,
...
...
@@ -101,12 +101,41 @@ class CupertinoTabView extends StatelessWidget {
/// This list of observers is not shared with ancestor or descendant [Navigator]s.
final
List
<
NavigatorObserver
>
navigatorObservers
;
@override
_CupertinoTabViewState
createState
()
{
return
new
_CupertinoTabViewState
();
}
}
class
_CupertinoTabViewState
extends
State
<
CupertinoTabView
>
{
HeroController
_heroController
;
List
<
NavigatorObserver
>
_navigatorObservers
;
@override
void
initState
()
{
super
.
initState
();
_heroController
=
new
HeroController
();
// Linear tweening.
_updateObservers
();
}
@override
void
didUpdateWidget
(
CupertinoTabView
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
_updateObservers
();
}
void
_updateObservers
()
{
_navigatorObservers
=
new
List
<
NavigatorObserver
>.
from
(
widget
.
navigatorObservers
)
..
add
(
_heroController
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
Navigator
(
onGenerateRoute:
_onGenerateRoute
,
onUnknownRoute:
_onUnknownRoute
,
observers:
navigatorObservers
,
observers:
_
navigatorObservers
,
);
}
...
...
@@ -114,12 +143,12 @@ class CupertinoTabView extends StatelessWidget {
final
String
name
=
settings
.
name
;
WidgetBuilder
routeBuilder
;
String
title
;
if
(
name
==
Navigator
.
defaultRouteName
&&
builder
!=
null
)
{
routeBuilder
=
builder
;
title
=
defaultTitle
;
if
(
name
==
Navigator
.
defaultRouteName
&&
widget
.
builder
!=
null
)
{
routeBuilder
=
widget
.
builder
;
title
=
widget
.
defaultTitle
;
}
else
if
(
routes
!=
null
)
routeBuilder
=
routes
[
name
];
else
if
(
widget
.
routes
!=
null
)
routeBuilder
=
widget
.
routes
[
name
];
if
(
routeBuilder
!=
null
)
{
return
new
CupertinoPageRoute
<
dynamic
>(
builder:
routeBuilder
,
...
...
@@ -127,14 +156,14 @@ class CupertinoTabView extends StatelessWidget {
settings:
settings
,
);
}
if
(
onGenerateRoute
!=
null
)
return
onGenerateRoute
(
settings
);
if
(
widget
.
onGenerateRoute
!=
null
)
return
widget
.
onGenerateRoute
(
settings
);
return
null
;
}
Route
<
dynamic
>
_onUnknownRoute
(
RouteSettings
settings
)
{
assert
(()
{
if
(
onUnknownRoute
==
null
)
{
if
(
widget
.
onUnknownRoute
==
null
)
{
throw
new
FlutterError
(
'Could not find a generator for route
$settings
in the
$runtimeType
.
\n
'
'Generators for routes are searched for in the following order:
\n
'
...
...
@@ -149,7 +178,7 @@ class CupertinoTabView extends StatelessWidget {
}
return
true
;
}());
final
Route
<
dynamic
>
result
=
onUnknownRoute
(
settings
);
final
Route
<
dynamic
>
result
=
widget
.
onUnknownRoute
(
settings
);
assert
(()
{
if
(
result
==
null
)
{
throw
new
FlutterError
(
...
...
packages/flutter/lib/src/widgets/heroes.dart
View file @
f23c9ae5
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/widgets/implicit_animations.dart
View file @
f23c9ae5
...
...
@@ -127,6 +127,24 @@ class BorderRadiusTween extends Tween<BorderRadius> {
BorderRadius
lerp
(
double
t
)
=>
BorderRadius
.
lerp
(
begin
,
end
,
t
);
}
/// An interpolation between two [Border]s.
///
/// This class specializes the interpolation of [Tween<Border>] to use
/// [Border.lerp].
///
/// See [Tween] for a discussion on how to use interpolation objects.
class
BorderTween
extends
Tween
<
Border
>
{
/// Creates a [Border] tween.
///
/// The [begin] and [end] properties may be null; the null value
/// is treated as having no border.
BorderTween
({
Border
begin
,
Border
end
})
:
super
(
begin:
begin
,
end:
end
);
/// Returns the value this variable has at the given animation clock value.
@override
Border
lerp
(
double
t
)
=>
Border
.
lerp
(
begin
,
end
,
t
);
}
/// An interpolation between two [Matrix4]s.
///
/// This class specializes the interpolation of [Tween<Matrix4>] to be
...
...
packages/flutter/lib/src/widgets/sliver_persistent_header.dart
View file @
f23c9ae5
...
...
@@ -188,6 +188,7 @@ class _SliverPersistentHeaderElement extends RenderObjectElement {
@override
void
performRebuild
()
{
super
.
performRebuild
();
renderObject
.
triggerRebuild
();
}
...
...
packages/flutter/lib/src/widgets/transitions.dart
View file @
f23c9ae5
...
...
@@ -10,6 +10,7 @@ import 'package:vector_math/vector_math_64.dart' show Matrix4;
import
'basic.dart'
;
import
'container.dart'
;
import
'framework.dart'
;
import
'text.dart'
;
export
'package:flutter/rendering.dart'
show
RelativeRect
;
...
...
@@ -671,6 +672,64 @@ class AlignTransition extends AnimatedWidget {
}
}
/// Animated version of a [DefaultTextStyle] that animates the different properties
/// of its [TextStyle].
///
/// See also:
///
/// * [DefaultTextStyle], which also defines a [TextStyle] for its descendants
/// but is not animated.
class
DefaultTextStyleTransition
extends
AnimatedWidget
{
/// Creates an animated [DefaultTextStyle] whose [TextStyle] animation updates
/// the widget.
const
DefaultTextStyleTransition
({
Key
key
,
@required
Animation
<
TextStyle
>
style
,
@required
this
.
child
,
this
.
textAlign
,
this
.
softWrap
=
true
,
this
.
overflow
=
TextOverflow
.
clip
,
this
.
maxLines
,
})
:
super
(
key:
key
,
listenable:
style
);
/// The animation that controls the descendants' text style.
Animation
<
TextStyle
>
get
style
=>
listenable
;
/// How the text should be aligned horizontally.
final
TextAlign
textAlign
;
/// Whether the text should break at soft line breaks.
///
/// See [DefaultTextStyle.softWrap] for more details.
final
bool
softWrap
;
/// How visual overflow should be handled.
///
final
TextOverflow
overflow
;
/// An optional maximum number of lines for the text to span, wrapping if necessary.
///
/// See [DefaultTextStyle.maxLines] for more details.
final
int
maxLines
;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final
Widget
child
;
@override
Widget
build
(
BuildContext
context
)
{
return
new
DefaultTextStyle
(
style:
style
.
value
,
textAlign:
textAlign
,
softWrap:
softWrap
,
overflow:
overflow
,
maxLines:
maxLines
,
child:
child
,
);
}
}
/// A general-purpose widget for building animations.
///
/// AnimatedBuilder is useful for more complex widgets that wish to include
...
...
packages/flutter/test/cupertino/nav_bar_test.dart
View file @
f23c9ae5
...
...
@@ -306,6 +306,65 @@ void main() {
expect
(
tester
.
getSize
(
find
.
widgetWithText
(
OverflowBox
,
'Title'
)).
height
,
0.0
);
});
testWidgets
(
'User specified middle is always visible in sliver'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
new
ScrollController
();
final
Key
segmentedControlsKey
=
new
UniqueKey
();
await
tester
.
pumpWidget
(
new
CupertinoApp
(
home:
new
CupertinoPageScaffold
(
child:
new
CustomScrollView
(
controller:
scrollController
,
slivers:
<
Widget
>[
new
CupertinoSliverNavigationBar
(
middle:
new
ConstrainedBox
(
constraints:
const
BoxConstraints
(
maxWidth:
200.0
),
child:
new
CupertinoSegmentedControl
<
int
>(
key:
segmentedControlsKey
,
children:
const
<
int
,
Widget
>{
0
:
Text
(
'Option A'
),
1
:
Text
(
'Option B'
),
},
onValueChanged:
(
int
selected
)
{
},
groupValue:
0
,
),
),
largeTitle:
const
Text
(
'Title'
),
),
new
SliverToBoxAdapter
(
child:
new
Container
(
height:
1200.0
,
),
),
],
),
),
),
);
expect
(
scrollController
.
offset
,
0.0
);
expect
(
tester
.
getTopLeft
(
find
.
byType
(
NavigationToolbar
)).
dy
,
0.0
);
expect
(
tester
.
getSize
(
find
.
byType
(
NavigationToolbar
)).
height
,
44.0
);
expect
(
find
.
text
(
'Title'
),
findsOneWidget
);
expect
(
tester
.
getCenter
(
find
.
byKey
(
segmentedControlsKey
)).
dx
,
400.0
);
expect
(
tester
.
getTopLeft
(
find
.
widgetWithText
(
OverflowBox
,
'Title'
)).
dy
,
44.0
);
expect
(
tester
.
getSize
(
find
.
widgetWithText
(
OverflowBox
,
'Title'
)).
height
,
52.0
);
scrollController
.
jumpTo
(
600.0
);
await
tester
.
pump
();
// Once to trigger the opacity animation.
await
tester
.
pump
(
const
Duration
(
milliseconds:
300
));
expect
(
tester
.
getCenter
(
find
.
byKey
(
segmentedControlsKey
)).
dx
,
400.0
);
// The large title is invisible now.
expect
(
tester
.
renderObject
<
RenderAnimatedOpacity
>(
find
.
widgetWithText
(
AnimatedOpacity
,
'Title'
)
).
opacity
.
value
,
0.0
,
);
});
testWidgets
(
'Small title can be overridden'
,
(
WidgetTester
tester
)
async
{
final
ScrollController
scrollController
=
new
ScrollController
();
await
tester
.
pumpWidget
(
...
...
@@ -390,7 +449,7 @@ void main() {
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
2
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
byType
(
CupertinoButton
),
findsOneWidget
);
expect
(
find
.
text
(
new
String
.
fromCharCode
(
CupertinoIcons
.
back
.
codePoint
)),
findsOneWidget
);
...
...
@@ -405,23 +464,22 @@ void main() {
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
2
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
byType
(
CupertinoButton
),
findsNWidgets
(
2
));
expect
(
find
.
text
(
'Close'
),
findsOneWidget
);
expect
(
find
.
widgetWithText
(
CupertinoButton
,
'Close'
),
findsOneWidget
);
// Test popping goes back correctly.
await
tester
.
tap
(
find
.
text
(
'Close'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
2
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
text
(
'Page 2'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
text
(
new
String
.
fromCharCode
(
CupertinoIcons
.
back
.
codePoint
)));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
2
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
text
(
'Home page'
),
findsOneWidget
);
});
...
...
@@ -438,7 +496,7 @@ void main() {
builder:
(
BuildContext
context
)
{
return
const
CupertinoPageScaffold
(
navigationBar:
CupertinoNavigationBar
(
previousPageTitle:
'0123456789'
,
previousPageTitle:
'0123456789
01
'
,
),
child:
Placeholder
(),
);
...
...
@@ -449,14 +507,14 @@ void main() {
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
expect
(
find
.
widgetWithText
(
CupertinoButton
,
'0123456789'
),
findsOneWidget
);
expect
(
find
.
widgetWithText
(
CupertinoButton
,
'0123456789
01
'
),
findsOneWidget
);
tester
.
state
<
NavigatorState
>(
find
.
byType
(
Navigator
)).
push
(
new
CupertinoPageRoute
<
void
>(
builder:
(
BuildContext
context
)
{
return
const
CupertinoPageScaffold
(
navigationBar:
CupertinoNavigationBar
(
previousPageTitle:
'01234567890'
,
previousPageTitle:
'01234567890
12
'
,
),
child:
Placeholder
(),
);
...
...
packages/flutter/test/cupertino/nav_bar_transition_test.dart
0 → 100644
View file @
f23c9ae5
This diff is collapsed.
Click to expand it.
packages/flutter/test/cupertino/route_test.dart
View file @
f23c9ae5
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
...
...
@@ -36,6 +37,71 @@ void main() {
expect
(
tester
.
getCenter
(
find
.
text
(
'An iPod'
)).
dx
,
400.0
);
});
testWidgets
(
'Large title auto-populates with title'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
CupertinoApp
(
home:
const
Placeholder
(),
),
);
tester
.
state
<
NavigatorState
>(
find
.
byType
(
Navigator
)).
push
(
new
CupertinoPageRoute
<
void
>(
title:
'An iPod'
,
builder:
(
BuildContext
context
)
{
return
new
CupertinoPageScaffold
(
child:
new
CustomScrollView
(
slivers:
const
<
Widget
>[
CupertinoSliverNavigationBar
(),
],
),
);
}
)
);
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
500
));
// There should be 2 Text widget with the title in the nav bar. One in the
// large title position and one in the middle position (though the middle
// position Text is initially invisible while the sliver is expanded).
expect
(
find
.
widgetWithText
(
CupertinoSliverNavigationBar
,
'An iPod'
),
findsNWidgets
(
2
),
);
final
List
<
Element
>
titles
=
tester
.
elementList
(
find
.
text
(
'An iPod'
))
.
toList
()
..
sort
((
Element
a
,
Element
b
)
{
final
RenderParagraph
aParagraph
=
a
.
renderObject
;
final
RenderParagraph
bParagraph
=
b
.
renderObject
;
return
aParagraph
.
text
.
style
.
fontSize
.
compareTo
(
bParagraph
.
text
.
style
.
fontSize
);
});
final
Iterable
<
double
>
opacities
=
titles
.
map
((
Element
element
)
{
final
RenderAnimatedOpacity
renderOpacity
=
element
.
ancestorRenderObjectOfType
(
const
TypeMatcher
<
RenderAnimatedOpacity
>());
return
renderOpacity
.
opacity
.
value
;
});
expect
(
opacities
,
<
double
>
[
0.0
,
// Initially the smaller font title is invisible.
1.0
,
// The larger font title is visible.
]);
// Check that the large font title is at the right spot.
expect
(
tester
.
getTopLeft
(
find
.
byWidget
(
titles
[
1
].
widget
)),
const
Offset
(
16.0
,
54.0
),
);
// The smaller, initially invisible title, should still be positioned in the
// center.
expect
(
tester
.
getCenter
(
find
.
byWidget
(
titles
[
0
].
widget
)).
dx
,
400.0
);
});
testWidgets
(
'Leading auto-populates with back button with previous title'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
CupertinoApp
(
...
...
packages/flutter/test/cupertino/scaffold_test.dart
View file @
f23c9ae5
...
...
@@ -239,7 +239,7 @@ void main() {
// Navigate in tab 2.
await
tester
.
tap
(
find
.
text
(
'Next'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
3
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
text
(
'Page 2 of tab 2'
),
isOnstage
);
expect
(
find
.
text
(
'Page 1 of tab 1'
,
skipOffstage:
false
),
isOffstage
);
...
...
@@ -254,7 +254,7 @@ void main() {
// Navigate in tab 1.
await
tester
.
tap
(
find
.
text
(
'Next'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
3
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
text
(
'Page 2 of tab 1'
),
isOnstage
);
expect
(
find
.
text
(
'Page 2 of tab 2'
,
skipOffstage:
false
),
isOffstage
);
...
...
@@ -268,7 +268,7 @@ void main() {
// Pop in tab 2
await
tester
.
tap
(
find
.
text
(
'Back'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
3
00
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
5
00
));
expect
(
find
.
text
(
'Page 1 of tab 2'
),
isOnstage
);
expect
(
find
.
text
(
'Page 2 of tab 1'
,
skipOffstage:
false
),
isOffstage
);
...
...
packages/flutter/test/widgets/heroes_test.dart
View file @
f23c9ae5
...
...
@@ -1244,4 +1244,95 @@ void main() {
await
tester
.
pump
(
duration
*
0.1
);
expect
(
tester
.
getTopLeft
(
find
.
byKey
(
firstKey
)).
dx
,
x0
);
});
testWidgets
(
'Can override flight shuttle'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Material
(
child:
new
ListView
(
children:
<
Widget
>[
const
Hero
(
tag:
'a'
,
child:
Text
(
'foo'
)),
new
Builder
(
builder:
(
BuildContext
context
)
{
return
new
FlatButton
(
child:
const
Text
(
'two'
),
onPressed:
()
=>
Navigator
.
push
<
void
>(
context
,
new
MaterialPageRoute
<
void
>(
builder:
(
BuildContext
context
)
{
return
new
Material
(
child:
new
Hero
(
tag:
'a'
,
child:
const
Text
(
'bar'
),
flightShuttleBuilder:
(
BuildContext
flightContext
,
Animation
<
double
>
animation
,
HeroFlightDirection
flightDirection
,
BuildContext
fromHeroContext
,
BuildContext
toHeroContext
,
)
{
return
const
Text
(
'baz'
);
},
),
);
},
)),
);
}),
],
),
),
));
await
tester
.
tap
(
find
.
text
(
'two'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
find
.
text
(
'foo'
),
findsNothing
);
expect
(
find
.
text
(
'bar'
),
findsNothing
);
expect
(
find
.
text
(
'baz'
),
findsOneWidget
);
});
testWidgets
(
'Can override flight launch pads'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Material
(
child:
new
ListView
(
children:
<
Widget
>[
new
Hero
(
tag:
'a'
,
child:
const
Text
(
'Batman'
),
placeholderBuilder:
(
BuildContext
context
,
Widget
child
)
{
return
const
Text
(
'Venom'
);
},
),
new
Builder
(
builder:
(
BuildContext
context
)
{
return
new
FlatButton
(
child:
const
Text
(
'two'
),
onPressed:
()
=>
Navigator
.
push
<
void
>(
context
,
new
MaterialPageRoute
<
void
>(
builder:
(
BuildContext
context
)
{
return
new
Material
(
child:
new
Hero
(
tag:
'a'
,
child:
const
Text
(
'Wolverine'
),
placeholderBuilder:
(
BuildContext
context
,
Widget
child
)
{
return
const
Text
(
'Joker'
);
},
),
);
},
)),
);
}),
],
),
),
));
await
tester
.
tap
(
find
.
text
(
'two'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
find
.
text
(
'Batman'
),
findsNothing
);
// This shows up once but in the Hero because by default, the destination
// Hero child is the widget in flight.
expect
(
find
.
text
(
'Wolverine'
),
findsOneWidget
);
expect
(
find
.
text
(
'Venom'
),
findsOneWidget
);
expect
(
find
.
text
(
'Joker'
),
findsOneWidget
);
});
}
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