Commit 1e908105 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Pesto favorite Recipe FAB should respond to taps within the app bar (#7059)

parent 0b737ac5
...@@ -17,6 +17,7 @@ class PestoDemo extends StatelessWidget { ...@@ -17,6 +17,7 @@ class PestoDemo extends StatelessWidget {
const String _kSmallLogoImage = 'packages/flutter_gallery_assets/pesto/logo_small.png'; const String _kSmallLogoImage = 'packages/flutter_gallery_assets/pesto/logo_small.png';
const String _kMediumLogoImage = 'packages/flutter_gallery_assets/pesto/logo_medium.png'; const String _kMediumLogoImage = 'packages/flutter_gallery_assets/pesto/logo_medium.png';
const double _kAppBarHeight = 128.0; const double _kAppBarHeight = 128.0;
const double _kFabHalfSize = 28.0; // TODO(mpcomplete): needs to adapt to screen size
const double _kRecipePageMaxWidth = 500.0; const double _kRecipePageMaxWidth = 500.0;
final Set<Recipe> _favoriteRecipes = new Set<Recipe>(); final Set<Recipe> _favoriteRecipes = new Set<Recipe>();
...@@ -24,7 +25,7 @@ final Set<Recipe> _favoriteRecipes = new Set<Recipe>(); ...@@ -24,7 +25,7 @@ final Set<Recipe> _favoriteRecipes = new Set<Recipe>();
final ThemeData _kTheme = new ThemeData( final ThemeData _kTheme = new ThemeData(
brightness: Brightness.light, brightness: Brightness.light,
primarySwatch: Colors.teal, primarySwatch: Colors.teal,
accentColor: Colors.redAccent[200] accentColor: Colors.redAccent[200],
); );
class PestoHome extends StatelessWidget { class PestoHome extends StatelessWidget {
...@@ -87,21 +88,21 @@ class _RecipeGridPageState extends State<RecipeGridPage> { ...@@ -87,21 +88,21 @@ class _RecipeGridPageState extends State<RecipeGridPage> {
key: scaffoldKey, key: scaffoldKey,
scrollableKey: config.scrollableKey, scrollableKey: config.scrollableKey,
appBarBehavior: AppBarBehavior.under, appBarBehavior: AppBarBehavior.under,
appBar: buildAppBar(context, statusBarHeight), appBar: _buildAppBar(context, statusBarHeight),
floatingActionButton: new FloatingActionButton( floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.edit), child: new Icon(Icons.edit),
onPressed: () { onPressed: () {
scaffoldKey.currentState.showSnackBar(new SnackBar( scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('Not supported.') content: new Text('Not supported.')
)); ));
} },
), ),
body: buildBody(context, statusBarHeight) body: _buildBody(context, statusBarHeight),
) )
); );
} }
Widget buildAppBar(BuildContext context, double statusBarHeight) { Widget _buildAppBar(BuildContext context, double statusBarHeight) {
return new AppBar( return new AppBar(
expandedHeight: _kAppBarHeight, expandedHeight: _kAppBarHeight,
actions: <Widget>[ actions: <Widget>[
...@@ -112,8 +113,8 @@ class _RecipeGridPageState extends State<RecipeGridPage> { ...@@ -112,8 +113,8 @@ class _RecipeGridPageState extends State<RecipeGridPage> {
scaffoldKey.currentState.showSnackBar(new SnackBar( scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('Not supported.') content: new Text('Not supported.')
)); ));
} },
) ),
], ],
flexibleSpace: new LayoutBuilder( flexibleSpace: new LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) { builder: (BuildContext context, BoxConstraints constraints) {
...@@ -125,18 +126,18 @@ class _RecipeGridPageState extends State<RecipeGridPage> { ...@@ -125,18 +126,18 @@ class _RecipeGridPageState extends State<RecipeGridPage> {
return new Padding( return new Padding(
padding: new EdgeInsets.only( padding: new EdgeInsets.only(
top: statusBarHeight + 0.5 * extraPadding, top: statusBarHeight + 0.5 * extraPadding,
bottom: extraPadding bottom: extraPadding,
), ),
child: new Center( child: new Center(
child: new PestoLogo(height: logoHeight, t: t.clamp(0.0, 1.0)) child: new PestoLogo(height: logoHeight, t: t.clamp(0.0, 1.0))
) ),
); );
} },
) ),
); );
} }
Widget buildBody(BuildContext context, double statusBarHeight) { Widget _buildBody(BuildContext context, double statusBarHeight) {
final EdgeInsets padding = new EdgeInsets.fromLTRB(8.0, 8.0 + _kAppBarHeight + statusBarHeight, 8.0, 8.0); final EdgeInsets padding = new EdgeInsets.fromLTRB(8.0, 8.0 + _kAppBarHeight + statusBarHeight, 8.0, 8.0);
return new ScrollableGrid( return new ScrollableGrid(
...@@ -152,14 +153,14 @@ class _RecipeGridPageState extends State<RecipeGridPage> { ...@@ -152,14 +153,14 @@ class _RecipeGridPageState extends State<RecipeGridPage> {
recipe: recipe, recipe: recipe,
onTap: () { showRecipePage(context, recipe); } onTap: () { showRecipePage(context, recipe); }
); );
}) }),
); );
} }
void showFavoritesPage(BuildContext context) { void showFavoritesPage(BuildContext context) {
Navigator.push(context, new MaterialPageRoute<Null>( Navigator.push(context, new MaterialPageRoute<Null>(
settings: const RouteSettings(name: "/pesto/favorites"), settings: const RouteSettings(name: "/pesto/favorites"),
builder: (BuildContext context) => new PestoFavorites() builder: (BuildContext context) => new PestoFavorites(),
)); ));
} }
...@@ -169,9 +170,9 @@ class _RecipeGridPageState extends State<RecipeGridPage> { ...@@ -169,9 +170,9 @@ class _RecipeGridPageState extends State<RecipeGridPage> {
builder: (BuildContext context) { builder: (BuildContext context) {
return new Theme( return new Theme(
data: _kTheme.copyWith(platform: Theme.of(context).platform), data: _kTheme.copyWith(platform: Theme.of(context).platform),
child: new RecipePage(recipe: recipe) child: new RecipePage(recipe: recipe),
); );
} },
)); ));
} }
} }
...@@ -200,7 +201,7 @@ class _PestoLogoState extends State<PestoLogo> { ...@@ -200,7 +201,7 @@ class _PestoLogoState extends State<PestoLogo> {
final Curve _textOpacity = const Interval(0.4, 1.0, curve: Curves.easeInOut); final Curve _textOpacity = const Interval(0.4, 1.0, curve: Curves.easeInOut);
final RectTween _imageRectTween = new RectTween( final RectTween _imageRectTween = new RectTween(
begin: new Rect.fromLTWH(0.0, 0.0, kLogoWidth, kLogoHeight), begin: new Rect.fromLTWH(0.0, 0.0, kLogoWidth, kLogoHeight),
end: new Rect.fromLTWH(0.0, 0.0, kLogoWidth, kImageHeight) end: new Rect.fromLTWH(0.0, 0.0, kLogoWidth, kImageHeight),
); );
@override @override
...@@ -215,18 +216,18 @@ class _PestoLogoState extends State<PestoLogo> { ...@@ -215,18 +216,18 @@ class _PestoLogoState extends State<PestoLogo> {
children: <Widget>[ children: <Widget>[
new Positioned.fromRect( new Positioned.fromRect(
rect: _imageRectTween.lerp(config.t), rect: _imageRectTween.lerp(config.t),
child: new Image.asset(_kSmallLogoImage, fit: ImageFit.contain) child: new Image.asset(_kSmallLogoImage, fit: ImageFit.contain),
), ),
new Positioned.fromRect( new Positioned.fromRect(
rect: _textRectTween.lerp(config.t), rect: _textRectTween.lerp(config.t),
child: new Opacity( child: new Opacity(
opacity: _textOpacity.transform(config.t), opacity: _textOpacity.transform(config.t),
child: new Text('PESTO', style: titleStyle, textAlign: TextAlign.center), child: new Text('PESTO', style: titleStyle, textAlign: TextAlign.center),
) ),
) ),
] ],
) ),
) ),
); );
} }
} }
...@@ -261,8 +262,8 @@ class RecipeCard extends StatelessWidget { ...@@ -261,8 +262,8 @@ class RecipeCard extends StatelessWidget {
child: new Image.asset( child: new Image.asset(
recipe.ingredientsImagePath, recipe.ingredientsImagePath,
width: 48.0, width: 48.0,
height: 48.0 height: 48.0,
) ),
), ),
new Expanded( new Expanded(
child: new Column( child: new Column(
...@@ -271,15 +272,15 @@ class RecipeCard extends StatelessWidget { ...@@ -271,15 +272,15 @@ class RecipeCard extends StatelessWidget {
children: <Widget>[ children: <Widget>[
new Text(recipe.name, style: titleStyle, softWrap: false, overflow: TextOverflow.ellipsis), new Text(recipe.name, style: titleStyle, softWrap: false, overflow: TextOverflow.ellipsis),
new Text(recipe.author, style: authorStyle), new Text(recipe.author, style: authorStyle),
] ],
) ),
) ),
] ],
) ),
) ),
] ],
) ),
) ),
); );
} }
} }
...@@ -310,7 +311,7 @@ class _RecipePageState extends State<RecipePage> { ...@@ -310,7 +311,7 @@ class _RecipePageState extends State<RecipePage> {
appBarBehavior: AppBarBehavior.scroll, appBarBehavior: AppBarBehavior.scroll,
appBar: new AppBar( appBar: new AppBar(
heroTag: _disableHeroTransition, heroTag: _disableHeroTransition,
expandedHeight: _getAppBarHeight(context), expandedHeight: _getAppBarHeight(context) - _kFabHalfSize,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
elevation: 0, elevation: 0,
actions: <Widget>[ actions: <Widget>[
...@@ -330,39 +331,40 @@ class _RecipePageState extends State<RecipePage> { ...@@ -330,39 +331,40 @@ class _RecipePageState extends State<RecipePage> {
gradient: new LinearGradient( gradient: new LinearGradient(
begin: const FractionalOffset(0.5, 0.0), begin: const FractionalOffset(0.5, 0.0),
end: const FractionalOffset(0.5, 0.40), end: const FractionalOffset(0.5, 0.40),
colors: <Color>[const Color(0x60000000), const Color(0x00000000)] colors: <Color>[const Color(0x60000000), const Color(0x00000000)],
) )
) )
) )
), ),
), ),
body: _buildContainer(context) body: _buildBody(context),
); );
} }
// The full page content with the recipe's image behind it. This // The full page content with the recipe's image behind it. This
// adjusts based on the size of the screen. If the recipe sheet touches // adjusts based on the size of the screen. If the recipe sheet touches
// the edge of the screen, use a slightly different layout. // the edge of the screen, use a slightly different layout.
Widget _buildContainer(BuildContext context) { Widget _buildBody(BuildContext context) {
debugPaintSizeEnabled = false;
debugPaintPointersEnabled = true;
final bool isFavorite = _favoriteRecipes.contains(config.recipe); final bool isFavorite = _favoriteRecipes.contains(config.recipe);
final Size screenSize = MediaQuery.of(context).size; final Size screenSize = MediaQuery.of(context).size;
final bool fullWidth = (screenSize.width < _kRecipePageMaxWidth); final bool fullWidth = (screenSize.width < _kRecipePageMaxWidth);
final double appBarHeight = _getAppBarHeight(context); final double appBarHeight = _getAppBarHeight(context);
const double fabHalfSize = 28.0; // TODO(mpcomplete): needs to adapt to screen size
return new Stack( return new Stack(
children: <Widget>[ children: <Widget>[
new Positioned( new Positioned(
top: 0.0, top: 0.0,
left: 0.0, left: 0.0,
right: 0.0, right: 0.0,
height: appBarHeight + fabHalfSize, height: appBarHeight + _kFabHalfSize,
child: new Hero( child: new Hero(
tag: config.recipe.imagePath, tag: config.recipe.imagePath,
child: new Image.asset( child: new Image.asset(
config.recipe.imagePath, config.recipe.imagePath,
fit: fullWidth ? ImageFit.fitWidth : ImageFit.cover fit: fullWidth ? ImageFit.fitWidth : ImageFit.cover,
) ),
) ),
), ),
new ClampOverscrolls( new ClampOverscrolls(
edge: ScrollableEdge.both, edge: ScrollableEdge.both,
...@@ -373,27 +375,25 @@ class _RecipePageState extends State<RecipePage> { ...@@ -373,27 +375,25 @@ class _RecipePageState extends State<RecipePage> {
padding: new EdgeInsets.only(top: appBarHeight), padding: new EdgeInsets.only(top: appBarHeight),
child: new Stack( child: new Stack(
children: <Widget>[ children: <Widget>[
new Padding( new Container(
padding: new EdgeInsets.only(top: fabHalfSize), padding: new EdgeInsets.only(top: _kFabHalfSize),
child: new SizedBox( width: fullWidth ? null : _kRecipePageMaxWidth,
width: fullWidth ? null : _kRecipePageMaxWidth, child: new RecipeSheet(recipe: config.recipe),
child: new RecipeSheet(recipe: config.recipe)
)
), ),
new Positioned( new Positioned(
right: 16.0, right: 16.0,
child: new FloatingActionButton( child: new FloatingActionButton(
child: new Icon(isFavorite ? Icons.favorite : Icons.favorite_border), child: new Icon(isFavorite ? Icons.favorite : Icons.favorite_border),
onPressed: _toggleFavorite onPressed: _toggleFavorite,
) ),
) ),
] ],
) ),
) ),
) ),
) ),
) ),
] ],
); );
} }
...@@ -405,9 +405,9 @@ class _RecipePageState extends State<RecipePage> { ...@@ -405,9 +405,9 @@ class _RecipePageState extends State<RecipePage> {
padding: const EdgeInsets.only(right: 24.0), padding: const EdgeInsets.only(right: 24.0),
child: new Icon(icon, color: Colors.black54) child: new Icon(icon, color: Colors.black54)
), ),
new Text(label, style: menuItemStyle) new Text(label, style: menuItemStyle),
] ],
) ),
); );
} }
...@@ -497,9 +497,9 @@ class RecipeSheet extends StatelessWidget { ...@@ -497,9 +497,9 @@ class RecipeSheet extends StatelessWidget {
(RecipeStep step) { (RecipeStep step) {
return _buildItemRow(step.duration ?? '', step.description); return _buildItemRow(step.duration ?? '', step.description);
} }
)) )),
) ),
) ),
); );
} }
...@@ -508,13 +508,13 @@ class RecipeSheet extends StatelessWidget { ...@@ -508,13 +508,13 @@ class RecipeSheet extends StatelessWidget {
children: <Widget>[ children: <Widget>[
new Padding( new Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.symmetric(vertical: 4.0),
child: new Text(left, style: itemAmountStyle) child: new Text(left, style: itemAmountStyle),
), ),
new Padding( new Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.symmetric(vertical: 4.0),
child: new Text(right, style: itemStyle) child: new Text(right, style: itemStyle),
) ),
] ],
); );
} }
} }
...@@ -569,8 +569,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -569,8 +569,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(description: 'Put in oven'), const RecipeStep(description: 'Put in oven'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Rustic purple mash', name: 'Rustic purple mash',
...@@ -587,8 +587,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -587,8 +587,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Bacon Sprouts', name: 'Bacon Sprouts',
...@@ -606,8 +606,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -606,8 +606,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Oven Sausage', name: 'Oven Sausage',
...@@ -621,8 +621,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -621,8 +621,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Chicken tostadas', name: 'Chicken tostadas',
...@@ -638,8 +638,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -638,8 +638,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Coconut rice', name: 'Coconut rice',
...@@ -657,7 +657,7 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -657,7 +657,7 @@ final List<Recipe> kPestoRecipes = <Recipe>[
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook')
] ],
), ),
const Recipe( const Recipe(
name: 'Gin basil cocktail', name: 'Gin basil cocktail',
...@@ -673,8 +673,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -673,8 +673,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Seared sesame fish', name: 'Seared sesame fish',
...@@ -692,8 +692,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -692,8 +692,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Herb artichoke', name: 'Herb artichoke',
...@@ -711,8 +711,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -711,8 +711,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Pesto bruschetta', name: 'Pesto bruschetta',
...@@ -732,8 +732,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -732,8 +732,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Garlic bok choy', name: 'Garlic bok choy',
...@@ -750,8 +750,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -750,8 +750,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Fresh Fettuccine', name: 'Fresh Fettuccine',
...@@ -769,8 +769,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -769,8 +769,8 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
const Recipe( const Recipe(
name: 'Sicilian-Style sardines', name: 'Sicilian-Style sardines',
...@@ -788,7 +788,7 @@ final List<Recipe> kPestoRecipes = <Recipe>[ ...@@ -788,7 +788,7 @@ final List<Recipe> kPestoRecipes = <Recipe>[
], ],
steps: const<RecipeStep>[ steps: const<RecipeStep>[
const RecipeStep(duration: '3 min', description: 'Stir'), const RecipeStep(duration: '3 min', description: 'Stir'),
const RecipeStep(duration: '45 min', description: 'Cook') const RecipeStep(duration: '45 min', description: 'Cook'),
] ],
), ),
]; ];
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment