mirror of
https://github.com/flutter/flutter
synced 2024-10-14 04:02:56 +00:00
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:
parent
82b7fc0d95
commit
4086e7a3c3
|
@ -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> {
|
|||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue