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
bfabb567
Commit
bfabb567
authored
Sep 19, 2016
by
Ian Hickson
Committed by
Adam Barth
Sep 19, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Docs for heroes (#5923)
parent
e04135e9
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
87 additions
and
36 deletions
+87
-36
heroes.dart
packages/flutter/lib/src/widgets/heroes.dart
+87
-36
No files found.
packages/flutter/lib/src/widgets/heroes.dart
View file @
bfabb567
...
...
@@ -15,39 +15,10 @@ import 'overlay.dart';
import
'pages.dart'
;
import
'transitions.dart'
;
// Heroes are the parts of an application's screen-to-screen transitions where a
// widget from one screen shifts to a position on the other. For example,
// album art from a list of albums growing to become the centerpiece of the
// album's details view. In this context, a screen is a navigator ModalRoute.
// To get this effect, all you have to do is wrap each hero on each route with a
// Hero widget, and give each hero a tag. The tag must either be unique within the
// current route's widget subtree. When the app transitions from one route to
// another, each hero is animated to its new location. If a hero is only
// present on one of the routes and not the other, then it will be made to
// appear or disappear as needed.
// TODO(ianh): Make the appear/disappear animations pretty. Right now they're
// pretty crude (just rotate and shrink the constraints). They should probably
// involve actually scaling and fading, at a minimum.
// Heroes and the Navigator's Stack must be axis-aligned for all this to work.
// The top left and bottom right coordinates of each animated Hero will be
// converted to global coordinates and then from there converted to the
// Navigator Stack's coordinate space, and the entire Hero subtree will, for the
// duration of the animation, be lifted out of its original place, and
// positioned on that stack. If the Hero isn't axis aligned, this is going to
// fail in a rather ugly fashion. Don't rotate your heroes!
// To make the animations look good, it's critical that the widget tree for the
// hero in both locations be essentially identical. The widget of the target is
// used to do the transition: when going from route A to route B, route B's
// hero's widget is placed over route A's hero's widget, and route A's hero is
// hidden. Then the widget is animated to route B's hero's position, and then
// the widget is inserted into route B. When going back from B to A, route A's
// hero's widget is placed over where route B's hero's widget was, and then the
// animation goes the other way.
// TODO(ianh): If the widgets use Inherited properties, they are taken from the
// Navigator's position in the widget hierarchy, not the source or target. We
// should interpolate the inherited properties from their value at the source to
...
...
@@ -73,28 +44,94 @@ abstract class _HeroHandle {
_HeroManifest
_takeChild
(
Animation
<
double
>
currentAnimation
);
}
/// A widget that marks its child as being a candidate for hero animations.
///
/// During a page transition (see [Navigator]), if a particular feature (e.g. a
/// picture or heading) appears on both pages, it can be helpful for orienting
/// the user if the feature appears to physically move from one page to the
/// other. Such an animation is called a *hero animation*.
///
/// To label a widget as such a feature, wrap it in a [Hero] widget. When a
/// navigation happens, the [Hero] widgets on each page are collected up. For
/// each pair of [Hero] widgets that have the same tag, a hero animation is
/// triggered.
///
/// Hero animations are managed by a [HeroController].
///
/// If a [Hero] is already in flight when another navigation occurs, then it
/// will continue to the next page.
///
/// A particular page must not have more than one [Hero] for each [tag].
///
/// ## Discussion
///
/// Heroes are the parts of an application's screen-to-screen transitions where
/// a widget from one screen shifts to a position on the other. For example,
/// album art from a list of albums growing to become the centerpiece of the
/// album's details view. In this context, a screen is a navigator ModalRoute.
///
/// To get this effect, all you have to do is wrap each hero on each route with a
/// [Hero] widget, and give each hero a [tag]. The tag must be unique within the
/// current route's widget subtree. When the app transitions from one route to
/// another, each hero is animated to its new location.
///
/// Heroes and the [Navigator]'s [Overlay]'s [Stack] must be axis-aligned for
/// all this to work. The top left and bottom right coordinates of each animated
/// [Hero] will be converted to global coordinates and then from there converted
/// to that [Stack]'s coordinate space, and the entire Hero subtree will, for
/// the duration of the animation, be lifted out of its original place, and
/// positioned on that stack. If the [Hero] isn't axis aligned, this is going to
/// fail in a rather ugly fashion. Don't rotate your heroes!
///
/// To make the animations look good, it's critical that the widget tree for the
/// hero in both locations be essentially identical. The widget of the *target*
/// is used to do the transition: when going from route A to route B, route B's
/// hero's widget is placed over route A's hero's widget, and route A's hero is
/// hidden. Then the widget is animated to route B's hero's position, and then
/// the widget is inserted into route B. When going back from B to A, route A's
/// hero's widget is placed over where route B's hero's widget was, and then the
/// animation goes the other way.
class
Hero
extends
StatefulWidget
{
/// Create a hero.
///
/// The [tag] and [child] are required.
Hero
({
Key
key
,
this
.
tag
,
this
.
child
,
@required
this
.
tag
,
this
.
turns
:
1
,
this
.
alwaysAnimate
:
false
this
.
alwaysAnimate
:
false
,
@required
this
.
child
,
})
:
super
(
key:
key
)
{
assert
(
tag
!=
null
);
assert
(
turns
!=
null
);
assert
(
alwaysAnimate
!=
null
);
assert
(
child
!=
null
);
}
/// The identifier for this particular hero. If the tag of this hero matches
/// the tag of a hero on the other page during a page transition, then a hero
/// animation will be triggered.
final
Object
tag
;
/// The widget below this widget in the tree.
final
Widget
child
;
/// The relative number of full rotations that the hero is conceptually at.
///
/// If a hero is animated from a [Hero] with [turns] set to 1 to a [Hero] with
/// [turns] set to 2, then it will turn by one full rotation during its
/// animation. Normally, all heroes have a [turns] value of 1.
final
int
turns
;
/// If true, the hero will always animate, even if it has no matching hero to
/// animate to or from.
/// animate to or from. If it has no target, it will imply a target at the
/// same position with zero width and height and with [turns] set to zero.
/// This will typically cause it to shrink and spin.
final
bool
alwaysAnimate
;
/// The widget below this widget in the tree.
///
/// This subtree should match the appearance of the subtrees of any other
/// heroes in the application with the same [tag].
final
Widget
child
;
/// Return a hero tag to _HeroState map of all of the heroes within the given subtree.
static
Map
<
Object
,
_HeroHandle
>
_of
(
BuildContext
context
)
{
final
Map
<
Object
,
_HeroHandle
>
result
=
<
Object
,
_HeroHandle
>{};
...
...
@@ -297,6 +334,12 @@ class _HeroMatch {
final
Object
tag
;
}
/// Signature for a function that takes two [Rect] instances and returns a
/// [RectTween] that transitions between them.
///
/// This is typically used with a [HeroController] to provide an animation for
/// [Hero] positions that looks nicer than a linear movement. For example, see
/// [MaterialRectArcTween].
typedef
RectTween
CreateRectTween
(
Rect
begin
,
Rect
end
);
class
_HeroParty
{
...
...
@@ -417,7 +460,15 @@ class _HeroParty {
String
toString
()
=>
'
$_heroes
'
;
}
/// A [Navigator] observer that manages [Hero] transitions.
///
/// An instance of [HeroController] should be used as the [Navigator.observer].
/// This is done automatically by [MaterialApp].
class
HeroController
extends
NavigatorObserver
{
/// Creates a hero controller with the given [RectTween] constructor if any.
///
/// The [createRectTween] argument is optional. By default, a linear
/// [RectTween] is used.
HeroController
({
CreateRectTween
createRectTween
})
{
_party
=
new
_HeroParty
(
onQuestFinished:
_handleQuestFinished
,
...
...
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