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
6f9bfbda
Commit
6f9bfbda
authored
Mar 15, 2017
by
Hans Muller
Committed by
GitHub
Mar 15, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support aborted hero flights (#8805)
parent
15330ffb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
122 additions
and
5 deletions
+122
-5
heroes.dart
packages/flutter/lib/src/widgets/heroes.dart
+15
-5
heroes_test.dart
packages/flutter/test/widgets/heroes_test.dart
+107
-0
No files found.
packages/flutter/lib/src/widgets/heroes.dart
View file @
6f9bfbda
...
...
@@ -222,6 +222,7 @@ class _HeroFlight {
ProxyAnimation
_proxyAnimation
;
_HeroFlightManifest
manifest
;
OverlayEntry
overlayEntry
;
bool
_aborted
=
false
;
RectTween
_doCreateRectTween
(
Rect
begin
,
Rect
end
)
{
if
(
manifest
.
createRectTween
!=
null
)
...
...
@@ -237,9 +238,10 @@ class _HeroFlight {
child:
manifest
.
toHero
.
config
,
builder:
(
BuildContext
context
,
Widget
child
)
{
final
RenderBox
toHeroBox
=
manifest
.
toHero
.
context
?.
findRenderObject
();
if
(
toHeroBox
==
null
||
!
toHeroBox
.
attached
)
{
// The toHero no longer exists. Continue flying while fading out.
if
(
_heroOpacity
==
kAlwaysCompleteAnimation
)
{
if
(
_aborted
||
toHeroBox
==
null
||
!
toHeroBox
.
attached
)
{
// The toHero no longer exists or it's no longer the flight's destination.
// Continue flying while fading out.
if
(
_heroOpacity
.
isCompleted
)
{
_heroOpacity
=
new
Tween
<
double
>(
begin:
1.0
,
end:
0.0
)
.
chain
(
new
CurveTween
(
curve:
new
Interval
(
_proxyAnimation
.
value
,
1.0
)))
.
animate
(
_proxyAnimation
);
...
...
@@ -294,6 +296,7 @@ class _HeroFlight {
// The simple case: we're either starting a push or a pop animation.
void
start
(
_HeroFlightManifest
initialManifest
)
{
assert
(!
_aborted
);
assert
(()
{
final
Animation
<
double
>
initial
=
initialManifest
.
animation
;
switch
(
initialManifest
.
type
)
{
...
...
@@ -305,6 +308,7 @@ class _HeroFlight {
});
manifest
=
initialManifest
;
if
(
manifest
.
type
==
_HeroFlightType
.
pop
)
_proxyAnimation
.
parent
=
new
ReverseAnimation
(
manifest
.
animation
);
else
...
...
@@ -388,9 +392,14 @@ class _HeroFlight {
newManifest
.
toHero
.
startFlight
();
}
_aborted
=
false
;
manifest
=
newManifest
;
}
void
abort
()
{
_aborted
=
true
;
}
@override
String
toString
()
{
final
RouteSettings
from
=
manifest
.
fromRoute
.
settings
;
...
...
@@ -418,8 +427,7 @@ class HeroController extends NavigatorObserver {
// All of the heroes that are currently in the overlay and in motion.
// Indexed by the hero tag.
// TBD: final?
Map
<
Object
,
_HeroFlight
>
_flights
=
<
Object
,
_HeroFlight
>{};
final
Map
<
Object
,
_HeroFlight
>
_flights
=
<
Object
,
_HeroFlight
>{};
@override
void
didPush
(
Route
<
dynamic
>
to
,
Route
<
dynamic
>
from
)
{
...
...
@@ -506,6 +514,8 @@ class HeroController extends NavigatorObserver {
_flights
[
tag
].
restart
(
manifest
);
else
_flights
[
tag
]
=
new
_HeroFlight
(
_handleFlightEnded
)..
start
(
manifest
);
}
else
if
(
_flights
[
tag
]
!=
null
)
{
_flights
[
tag
].
abort
();
}
}
}
...
...
packages/flutter/test/widgets/heroes_test.dart
View file @
6f9bfbda
...
...
@@ -4,6 +4,7 @@
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
Key
firstKey
=
const
Key
(
'first'
);
Key
secondKey
=
const
Key
(
'second'
);
...
...
@@ -804,4 +805,110 @@ void main() {
expect
(
find
.
byKey
(
routeHeroKey
),
findsNothing
);
});
testWidgets
(
'Aborted flight'
,
(
WidgetTester
tester
)
async
{
// See https://github.com/flutter/flutter/issues/5798
final
Key
heroABKey
=
const
Key
(
'AB hero'
);
final
Key
heroBCKey
=
const
Key
(
'BC hero'
);
// Show a 150x150 Hero tagged 'BC'
final
MaterialPageRoute
<
Null
>
routeC
=
new
MaterialPageRoute
<
Null
>(
builder:
(
BuildContext
context
)
{
return
new
Material
(
child:
new
ListView
(
children:
<
Widget
>[
// This container will appear at Y=0
new
Container
(
child:
new
Hero
(
tag:
'BC'
,
child:
new
Container
(
key:
heroBCKey
,
height:
150.0
))
),
new
SizedBox
(
height:
800.0
),
],
)
);
},
);
// Show a height=200 Hero tagged 'AB' and a height=50 Hero tagged 'BC'
final
MaterialPageRoute
<
Null
>
routeB
=
new
MaterialPageRoute
<
Null
>(
builder:
(
BuildContext
context
)
{
return
new
Material
(
child:
new
ListView
(
children:
<
Widget
>[
new
SizedBox
(
height:
100.0
),
// This container will appear at Y=100
new
Container
(
child:
new
Hero
(
tag:
'AB'
,
child:
new
Container
(
key:
heroABKey
,
height:
200.0
))
),
new
FlatButton
(
child:
new
Text
(
'PUSH C'
),
onPressed:
()
{
Navigator
.
push
(
context
,
routeC
);
}
),
new
Container
(
child:
new
Hero
(
tag:
'BC'
,
child:
new
Container
(
height:
150.0
))
),
new
SizedBox
(
height:
800.0
),
],
)
);
},
);
// Show a 100x100 Hero tagged 'AB' with key heroABKey
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Scaffold
(
body:
new
Builder
(
builder:
(
BuildContext
context
)
{
// Navigator.push() needs context
return
new
ListView
(
children:
<
Widget
>
[
new
SizedBox
(
height:
200.0
),
// This container will appear at Y=200
new
Container
(
child:
new
Hero
(
tag:
'AB'
,
child:
new
Container
(
height:
100.0
,
width:
100.0
)),
),
new
FlatButton
(
child:
new
Text
(
'PUSH B'
),
onPressed:
()
{
Navigator
.
push
(
context
,
routeB
);
}
),
],
);
},
),
),
)
);
// Pushes routeB
await
tester
.
tap
(
find
.
text
(
'PUSH B'
));
await
tester
.
pump
();
await
tester
.
pump
();
final
double
initialY
=
tester
.
getTopLeft
(
find
.
byKey
(
heroABKey
)).
y
;
expect
(
initialY
,
200.0
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
final
double
yAt200ms
=
tester
.
getTopLeft
(
find
.
byKey
(
heroABKey
)).
y
;
// Hero AB is mid flight.
expect
(
yAt200ms
,
lessThan
(
200.0
));
expect
(
yAt200ms
,
greaterThan
(
100.0
));
// Pushes route C, causes hero AB's flight to abort, hero BC's flight to start
await
tester
.
tap
(
find
.
text
(
'PUSH C'
));
await
tester
.
pump
();
await
tester
.
pump
();
// Hero AB's aborted flight finishes where it was expected although
// it's been faded out.
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
expect
(
tester
.
getTopLeft
(
find
.
byKey
(
heroABKey
)).
y
,
100.0
);
// One Opacity widget per Hero, only one now has opacity 0.0
final
Iterable
<
RenderOpacity
>
renderers
=
tester
.
renderObjectList
(
find
.
byType
(
Opacity
));
final
Iterable
<
double
>
opacities
=
renderers
.
map
((
RenderOpacity
r
)
=>
r
.
opacity
);
expect
(
opacities
.
singleWhere
((
double
opacity
)
=>
opacity
==
0.0
),
0.0
);
// Hero BC's flight finishes normally.
await
tester
.
pump
(
const
Duration
(
milliseconds:
300
));
expect
(
tester
.
getTopLeft
(
find
.
byKey
(
heroBCKey
)).
y
,
0.0
);
});
}
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