From a010d6eb0829ccd1870f0d0f3f5e9cc4484bbf5c Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Wed, 17 Aug 2016 15:30:57 -0700 Subject: [PATCH] Rearrange the Pesto internals (#5466) --- .../flutter_gallery/lib/demo/pesto_demo.dart | 209 ++++++++++-------- 1 file changed, 116 insertions(+), 93 deletions(-) diff --git a/examples/flutter_gallery/lib/demo/pesto_demo.dart b/examples/flutter_gallery/lib/demo/pesto_demo.dart index 0ca3f44477d..7a844172298 100644 --- a/examples/flutter_gallery/lib/demo/pesto_demo.dart +++ b/examples/flutter_gallery/lib/demo/pesto_demo.dart @@ -6,76 +6,106 @@ import 'dart:math'; import 'package:flutter/material.dart'; +class PestoDemo extends StatelessWidget { + PestoDemo({ Key key }) : super(key: key); + + static const String routeName = '/pesto'; + + @override + Widget build(BuildContext context) => new PestoHome(); +} + const String _kUserName = 'Jonathan'; const String _kUserEmail = 'jonathan@example.com'; const String _kUserImage = 'packages/flutter_gallery_assets/pesto/avatar.jpg'; - const String _kSmallLogoImage = 'packages/flutter_gallery_assets/pesto/logo_small.png'; const String _kMediumLogoImage = 'packages/flutter_gallery_assets/pesto/logo_medium.png'; +const double _kAppBarHeight = 128.0; +const double _kRecipePageMaxWidth = 500.0; + +final Set _favoriteRecipes = new Set(); final ThemeData _kTheme = new ThemeData( brightness: Brightness.light, primarySwatch: Colors.teal, accentColor: Colors.redAccent[200] ); -const String _kFontFace = 'Raleway'; -const double _kAppBarHeight = 128.0; -const double _kRecipePageMaxWidth = 500.0; -Set favoriteRecipes = new Set(); - -// Helper for common Pesto text style properties. -TextStyle _textStyle(double size, [FontWeight fontWeight]) { - return new TextStyle( - inherit: false, - fontSize: size, - fontWeight: fontWeight, - fontFamily: 'Raleway', - color: Colors.black87, - textBaseline: TextBaseline.alphabetic - ); -} - -class PestoDemo extends StatefulWidget { - PestoDemo({ Key key, this.showFavorites: false }) : super(key: key); - - static const String routeName = '/pesto'; - - final bool showFavorites; - - @override - _PestoDemoState createState() => new _PestoDemoState(); -} - -class _PestoDemoState extends State { - final GlobalKey _scaffoldKey = new GlobalKey(); - static final GlobalKey _homeScrollableKey = new GlobalKey(); - static final GlobalKey _favoritesScrollableKey = new GlobalKey(); - final TextStyle favoritesMessageStyle = _textStyle(16.0); - final TextStyle userStyle = _textStyle(12.0, FontWeight.bold); - final TextStyle emailStyle = _textStyle(12.0).copyWith(color: Colors.black54); +class PestoHome extends StatelessWidget { + static final GlobalKey scrollableKey = new GlobalKey(); @override Widget build(BuildContext context) { + return new RecipeGridPage(recipes: kPestoRecipes, scrollableKey: scrollableKey); + } +} + +class PestoFavorites extends StatelessWidget { + static final GlobalKey scrollableKey = new GlobalKey(); + + @override + Widget build(BuildContext context) { + return new RecipeGridPage(recipes: _favoriteRecipes.toList(), scrollableKey: scrollableKey); + } +} + +class PestoStyle extends TextStyle { + const PestoStyle({ + double fontSize: 12.0, + FontWeight fontWeight, + Color color: Colors.black87, + double height + }) : super( + inherit: false, + color: color, + fontFamily: 'Raleway', + fontSize: fontSize, + fontWeight: fontWeight, + textBaseline: TextBaseline.alphabetic, + height: height + ); +} + +// Displays a grid of recipe cards. +class RecipeGridPage extends StatefulWidget { + RecipeGridPage({ Key key, this.recipes, this.scrollableKey }) : super(key: key); + + final List recipes; + final GlobalKey scrollableKey; + + @override + _RecipeGridPageState createState() => new _RecipeGridPageState(); +} + +class _RecipeGridPageState extends State { + final GlobalKey scaffoldKey = new GlobalKey(); + final TextStyle favoritesMessageStyle = const PestoStyle(fontSize: 16.0); + final TextStyle userStyle = const PestoStyle(fontWeight: FontWeight.bold); + final TextStyle emailStyle = const PestoStyle(color: Colors.black54); + + bool showFavorites = false; + + @override + Widget build(BuildContext context) { + final double statusBarHeight = MediaQuery.of(context).padding.top; return new Theme( data: _kTheme, child: new Scaffold( - key: _scaffoldKey, - scrollableKey: config.showFavorites ? _favoritesScrollableKey : _homeScrollableKey, + key: scaffoldKey, + scrollableKey: config.scrollableKey, appBarBehavior: AppBarBehavior.under, - appBar: _buildAppBar(context), - drawer: _buildDrawer(context), + appBar: buildAppBar(context, statusBarHeight), + drawer: buildDrawer(context), floatingActionButton: new FloatingActionButton( child: new Icon(Icons.edit), onPressed: () { } ), - body: _buildBody(context) + body: buildBody(context, statusBarHeight) ) ); } - Widget _buildAppBar(BuildContext context) { - final double statusBarHeight = MediaQuery.of(context).padding.top; + Widget buildAppBar(BuildContext context, double statusBarHeight) { return new AppBar( expandedHeight: _kAppBarHeight, actions: [ @@ -83,7 +113,7 @@ class _PestoDemoState extends State { icon: new Icon(Icons.search), tooltip: 'Search', onPressed: () { - _scaffoldKey.currentState.showSnackBar(new SnackBar( + scaffoldKey.currentState.showSnackBar(new SnackBar( content: new Text('Not supported.') )); } @@ -111,7 +141,7 @@ class _PestoDemoState extends State { ); } - Widget _buildDrawer(BuildContext context) { + Widget buildDrawer(BuildContext context) { return new Drawer( child: new Block( children: [ @@ -139,19 +169,19 @@ class _PestoDemoState extends State { ), new DrawerItem( child: new Text('Home'), - selected: !config.showFavorites, + selected: !showFavorites, onPressed: () { Navigator.popUntil(context, ModalRoute.withName('/pesto')); } ), new DrawerItem( child: new Text('Favorites'), - selected: config.showFavorites, + selected: showFavorites, onPressed: () { - if (config.showFavorites) + if (showFavorites) Navigator.pop(context); else - _showFavorites(context); + showFavoritesPage(context); } ), new Divider(), @@ -166,12 +196,10 @@ class _PestoDemoState extends State { ); } - Widget _buildBody(BuildContext context) { - final double statusBarHeight = MediaQuery.of(context).padding.top; - List recipes = config.showFavorites ? favoriteRecipes.toList() : kRecipes; + Widget buildBody(BuildContext context, double statusBarHeight) { final EdgeInsets padding = new EdgeInsets.fromLTRB(8.0, 8.0 + _kAppBarHeight + statusBarHeight, 8.0, 8.0); - if (config.showFavorites && recipes.isEmpty) { + if (config.recipes.isEmpty) { return new Padding( padding: padding, child: new Text('Save your favorite recipes to see them here.', style: favoritesMessageStyle) @@ -179,50 +207,48 @@ class _PestoDemoState extends State { } return new ScrollableGrid( - scrollableKey: config.showFavorites ? _favoritesScrollableKey : _homeScrollableKey, + scrollableKey: config.scrollableKey, delegate: new MaxTileWidthGridDelegate( - maxTileWidth: 500.0, + maxTileWidth: _kRecipePageMaxWidth, rowSpacing: 8.0, columnSpacing: 8.0, padding: padding ), - children: recipes.map( - (Recipe recipe) => new _RecipeCard( + children: config.recipes.map((Recipe recipe) { + return new RecipeCard( recipe: recipe, - onTap: () { _showRecipe(context, recipe); } - ) - ) + onTap: () { showRecipePage(context, recipe); } + ); + }) ); } - void _showFavorites(BuildContext context) { + void showFavoritesPage(BuildContext context) { Navigator.push(context, new MaterialPageRoute( settings: const RouteSettings(name: "/pesto/favorites"), - builder: (BuildContext context) { - return new PestoDemo(showFavorites: true); - } + builder: (BuildContext context) => new PestoFavorites() )); } - void _showRecipe(BuildContext context, Recipe recipe) { + void showRecipePage(BuildContext context, Recipe recipe) { Navigator.push(context, new MaterialPageRoute( settings: const RouteSettings(name: "/pesto/recipe"), builder: (BuildContext context) { return new Theme( data: _kTheme, - child: new _RecipePage(recipe: recipe) + child: new RecipePage(recipe: recipe) ); } )); } } -/// A short recipe card to be displayed in a grid. -class _RecipeCard extends StatelessWidget { - final TextStyle titleStyle = _textStyle(24.0, FontWeight.w600); - final TextStyle authorStyle = _textStyle(12.0, FontWeight.w500).copyWith(color: Colors.black54); +// A card with the recipe's image, author, and title. +class RecipeCard extends StatelessWidget { + final TextStyle titleStyle = const PestoStyle(fontSize: 24.0, fontWeight: FontWeight.w600); + final TextStyle authorStyle = const PestoStyle(fontWeight: FontWeight.w500, color: Colors.black54); - _RecipeCard({ Key key, this.recipe, this.onTap }) : super(key: key); + RecipeCard({ Key key, this.recipe, this.onTap }) : super(key: key); final Recipe recipe; final VoidCallback onTap; @@ -270,10 +296,9 @@ class _RecipeCard extends StatelessWidget { } } -/// A page displaying a single recipe. Includes the recipe sheet with a -/// background image. -class _RecipePage extends StatefulWidget { - _RecipePage({ Key key, this.recipe }) : super(key: key); +// Displays one recipe. Includes the recipe sheet with a background image. +class RecipePage extends StatefulWidget { + RecipePage({ Key key, this.recipe }) : super(key: key); final Recipe recipe; @@ -281,10 +306,10 @@ class _RecipePage extends StatefulWidget { _RecipePageState createState() => new _RecipePageState(); } -class _RecipePageState extends State<_RecipePage> { +class _RecipePageState extends State { final GlobalKey _scaffoldKey = new GlobalKey(); final GlobalKey _scrollableKey = new GlobalKey(); - final TextStyle menuItemStyle = _textStyle(15.0).copyWith(color: Colors.black54, height: 24.0/15.0); + final TextStyle menuItemStyle = new PestoStyle(fontSize: 15.0, color: Colors.black54, height: 24.0/15.0); double _getAppBarHeight(BuildContext context) => MediaQuery.of(context).size.height * 0.3; @@ -326,7 +351,7 @@ class _RecipePageState extends State<_RecipePage> { // adjusts based on the size of the screen. If the recipe sheet touches // the edge of the screen, use a slightly different layout. Widget _buildContainer(BuildContext context) { - final bool isFavorite = favoriteRecipes.contains(config.recipe); + final bool isFavorite = _favoriteRecipes.contains(config.recipe); final Size screenSize = MediaQuery.of(context).size; final bool fullWidth = (screenSize.width < _kRecipePageMaxWidth); final double appBarHeight = _getAppBarHeight(context); @@ -359,7 +384,7 @@ class _RecipePageState extends State<_RecipePage> { padding: new EdgeInsets.only(top: fabHalfSize), child: new SizedBox( width: fullWidth ? null : _kRecipePageMaxWidth, - child: new _RecipeSheet(recipe: config.recipe) + child: new RecipeSheet(recipe: config.recipe) ) ), new Positioned( @@ -395,23 +420,23 @@ class _RecipePageState extends State<_RecipePage> { void _toggleFavorite() { setState(() { - if (favoriteRecipes.contains(config.recipe)) - favoriteRecipes.remove(config.recipe); + if (_favoriteRecipes.contains(config.recipe)) + _favoriteRecipes.remove(config.recipe); else - favoriteRecipes.add(config.recipe); + _favoriteRecipes.add(config.recipe); }); } } -/// The sheet with the recipe name and instructions. -class _RecipeSheet extends StatelessWidget { - final TextStyle titleStyle = _textStyle(34.0); - final TextStyle descriptionStyle = _textStyle(15.0).copyWith(color: Colors.black54, height: 24.0/15.0); - final TextStyle itemStyle = _textStyle(15.0).copyWith(height: 24.0/15.0); - final TextStyle itemAmountStyle = _textStyle(15.0).copyWith(color: _kTheme.primaryColor, height: 24.0/15.0); - final TextStyle headingStyle = _textStyle(15.0).copyWith(fontSize: 16.0, fontWeight: FontWeight.bold, height: 24.0/15.0); +/// Displays the recipe's name and instructions. +class RecipeSheet extends StatelessWidget { + final TextStyle titleStyle = const PestoStyle(fontSize: 34.0); + final TextStyle descriptionStyle = const PestoStyle(fontSize: 15.0, color: Colors.black54, height: 24.0/15.0); + final TextStyle itemStyle = const PestoStyle(fontSize: 15.0, height: 24.0/15.0); + final TextStyle itemAmountStyle = new PestoStyle(fontSize: 15.0, color: _kTheme.primaryColor, height: 24.0/15.0); + final TextStyle headingStyle = const PestoStyle(fontSize: 16.0, fontWeight: FontWeight.bold, height: 24.0/15.0); - _RecipeSheet({ Key key, this.recipe }) : super(key: key); + RecipeSheet({ Key key, this.recipe }) : super(key: key); final Recipe recipe; @@ -501,8 +526,6 @@ class _RecipeSheet extends StatelessWidget { } } -// Data models for the UI. - class Recipe { const Recipe({ this.name, @@ -537,7 +560,7 @@ class RecipeStep { final String description; } -final List kRecipes = [ +final List kPestoRecipes = [ const Recipe( name: 'Pesto Bruchetta', author: 'Peter Carlsson',