Improve performance of Pesto hero animation (#5182)

Previously we were resizing a paragraph of text during the animation. Now we
animate the text and the image separately. Also, add a default hero tag for
FloatingActionButton so that it animates as part of the hero transition as
well.
This commit is contained in:
Adam Barth 2016-08-02 11:35:15 -07:00 committed by GitHub
parent 82b7fc0d95
commit 4086e7a3c3
2 changed files with 67 additions and 55 deletions

View file

@ -232,37 +232,37 @@ class _RecipeCard extends StatelessWidget {
Widget build(BuildContext context) {
return new GestureDetector(
onTap: onTap,
child: new Hero(
tag: recipe.imagePath,
child: new Card(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Image.asset(recipe.imagePath, fit: ImageFit.contain),
new Flexible(
child: new Row(
children: <Widget>[
new Padding(
padding: const EdgeInsets.all(16.0),
child: new Image.asset(
recipe.ingredientsImagePath,
width: 48.0,
height: 48.0
)
),
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(recipe.name, style: titleStyle),
new Text(recipe.author, style: authorStyle),
]
child: new Card(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Hero(
tag: recipe.imagePath,
child: new Image.asset(recipe.imagePath, fit: ImageFit.contain)
),
new Flexible(
child: new Row(
children: <Widget>[
new Padding(
padding: const EdgeInsets.all(16.0),
child: new Image.asset(
recipe.ingredientsImagePath,
width: 48.0,
height: 48.0
)
]
)
),
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(recipe.name, style: titleStyle),
new Text(recipe.author, style: authorStyle),
]
)
]
)
]
)
)
]
)
)
);
@ -327,21 +327,23 @@ class _RecipePageState extends State<_RecipePage> {
Size screenSize = MediaQuery.of(context).size;
bool fullWidth = (screenSize.width < _kRecipePageMaxWidth);
const double fabHalfSize = 28.0; // TODO(mpcomplete): needs to adapt to screen size
return new Hero(
tag: config.recipe.imagePath,
child: new Container(
decoration: new BoxDecoration(
backgroundColor: Theme.of(context).canvasColor,
backgroundImage: new BackgroundImage(
image: new AssetImage(config.recipe.imagePath),
alignment: FractionalOffset.topCenter,
fit: fullWidth ? ImageFit.fitWidth : ImageFit.cover
return new Stack(
children: <Widget>[
new Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: new Hero(
tag: config.recipe.imagePath,
child: new Image.asset(
config.recipe.imagePath,
fit: fullWidth ? ImageFit.fitWidth : ImageFit.cover
)
)
),
align: FractionalOffset.bottomCenter,
child: new Block(
children: <Widget>[
new Padding(
new ScrollableViewport(
child: new RepaintBoundary(
child: new Padding(
padding: new EdgeInsets.only(top: _getAppBarHeight(context)),
child: new Stack(
children: <Widget>[
@ -362,9 +364,9 @@ class _RecipePageState extends State<_RecipePage> {
]
)
)
]
)
)
)
]
);
}

View file

@ -17,6 +17,7 @@ import 'tooltip.dart';
// http://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-keylines-spacing
const double _kSize = 56.0;
const double _kSizeMini = 40.0;
final Object _kDefaultHeroTag = new Object();
/// A material design floating action button.
///
@ -46,6 +47,7 @@ class FloatingActionButton extends StatefulWidget {
@required this.child,
this.tooltip,
this.backgroundColor,
this.heroTag,
this.elevation: 6,
this.highlightElevation: 12,
@required this.onPressed,
@ -66,6 +68,11 @@ class FloatingActionButton extends StatefulWidget {
/// Defaults to the accent color of the current theme.
final Color backgroundColor;
/// The tag to apply to the button's [Hero] widget.
///
/// Defaults to a tag that matches other floating action buttons.
final Object heroTag;
/// The callback that is called when the button is tapped or otherwise activated.
///
/// If this is set to null, the button will be disabled.
@ -124,17 +131,20 @@ class _FloatingActionButtonState extends State<FloatingActionButton> {
);
}
return new Material(
color: materialColor,
type: MaterialType.circle,
elevation: _highlight ? config.highlightElevation : config.elevation,
child: new Container(
width: config.mini ? _kSizeMini : _kSize,
height: config.mini ? _kSizeMini : _kSize,
child: new InkWell(
onTap: config.onPressed,
onHighlightChanged: _handleHighlightChanged,
child: result
return new Hero(
tag: config.heroTag ?? _kDefaultHeroTag,
child: new Material(
color: materialColor,
type: MaterialType.circle,
elevation: _highlight ? config.highlightElevation : config.elevation,
child: new Container(
width: config.mini ? _kSizeMini : _kSize,
height: config.mini ? _kSizeMini : _kSize,
child: new InkWell(
onTap: config.onPressed,
onHighlightChanged: _handleHighlightChanged,
child: result
)
)
)
);