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
9192f672
Commit
9192f672
authored
Mar 27, 2017
by
Hans Muller
Committed by
GitHub
Mar 27, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Shrine gallery demo: support for landscape layout (#9025)
parent
23981f59
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
274 additions
and
200 deletions
+274
-200
shrine_home.dart
examples/flutter_gallery/lib/demo/shrine/shrine_home.dart
+93
-96
shrine_order.dart
examples/flutter_gallery/lib/demo/shrine/shrine_order.dart
+181
-104
No files found.
examples/flutter_gallery/lib/demo/shrine/shrine_home.dart
View file @
9192f672
...
@@ -47,8 +47,8 @@ int _columnSpanAtIndex(int index) {
...
@@ -47,8 +47,8 @@ int _columnSpanAtIndex(int index) {
// The Shrine home page arranges the product cards into two columns. The card
// The Shrine home page arranges the product cards into two columns. The card
// on every 4th and 5th row spans two columns.
// on every 4th and 5th row spans two columns.
class
ShrineGridLayout
extends
SliverGridLayout
{
class
_
ShrineGridLayout
extends
SliverGridLayout
{
const
ShrineGridLayout
({
const
_
ShrineGridLayout
({
@required
this
.
rowStride
,
@required
this
.
rowStride
,
@required
this
.
columnStride
,
@required
this
.
columnStride
,
@required
this
.
tileHeight
,
@required
this
.
tileHeight
,
...
@@ -95,14 +95,14 @@ class ShrineGridLayout extends SliverGridLayout {
...
@@ -95,14 +95,14 @@ class ShrineGridLayout extends SliverGridLayout {
}
}
}
}
class
ShrineGridDelegate
extends
SliverGridDelegate
{
class
_
ShrineGridDelegate
extends
SliverGridDelegate
{
static
const
double
_kSpacing
=
8.0
;
static
const
double
_kSpacing
=
8.0
;
@override
@override
SliverGridLayout
getLayout
(
SliverConstraints
constraints
)
{
SliverGridLayout
getLayout
(
SliverConstraints
constraints
)
{
final
double
tileWidth
=
(
constraints
.
crossAxisExtent
-
_kSpacing
)
/
2.0
;
final
double
tileWidth
=
(
constraints
.
crossAxisExtent
-
_kSpacing
)
/
2.0
;
final
double
tileHeight
=
40.0
+
144.0
+
40.0
;
final
double
tileHeight
=
40.0
+
144.0
+
40.0
;
return
new
ShrineGridLayout
(
return
new
_
ShrineGridLayout
(
tileWidth:
tileWidth
,
tileWidth:
tileWidth
,
tileHeight:
tileHeight
,
tileHeight:
tileHeight
,
rowStride:
tileHeight
+
_kSpacing
,
rowStride:
tileHeight
+
_kSpacing
,
...
@@ -114,9 +114,9 @@ class ShrineGridDelegate extends SliverGridDelegate {
...
@@ -114,9 +114,9 @@ class ShrineGridDelegate extends SliverGridDelegate {
bool
shouldRelayout
(
covariant
SliverGridDelegate
oldDelegate
)
=>
false
;
bool
shouldRelayout
(
covariant
SliverGridDelegate
oldDelegate
)
=>
false
;
}
}
//
/
Displays the Vendor's name and avatar.
// Displays the Vendor's name and avatar.
class
VendorItem
extends
StatelessWidget
{
class
_
VendorItem
extends
StatelessWidget
{
VendorItem
({
Key
key
,
this
.
vendor
})
:
super
(
key:
key
)
{
_
VendorItem
({
Key
key
,
this
.
vendor
})
:
super
(
key:
key
)
{
assert
(
vendor
!=
null
);
assert
(
vendor
!=
null
);
}
}
...
@@ -145,10 +145,10 @@ class VendorItem extends StatelessWidget {
...
@@ -145,10 +145,10 @@ class VendorItem extends StatelessWidget {
}
}
}
}
//
/ Displays the product's price. If the product is in the shopping cart the background
//
Displays the product's price. If the product is in the shopping cart then the
//
/
is highlighted.
//
background
is highlighted.
abstract
class
PriceItem
extends
StatelessWidget
{
abstract
class
_
PriceItem
extends
StatelessWidget
{
PriceItem
({
Key
key
,
this
.
product
})
:
super
(
key:
key
)
{
_
PriceItem
({
Key
key
,
this
.
product
})
:
super
(
key:
key
)
{
assert
(
product
!=
null
);
assert
(
product
!=
null
);
}
}
...
@@ -167,8 +167,8 @@ abstract class PriceItem extends StatelessWidget {
...
@@ -167,8 +167,8 @@ abstract class PriceItem extends StatelessWidget {
}
}
}
}
class
ProductPriceItem
extends
PriceItem
{
class
_ProductPriceItem
extends
_
PriceItem
{
ProductPriceItem
({
Key
key
,
Product
product
})
:
super
(
key:
key
,
product:
product
);
_
ProductPriceItem
({
Key
key
,
Product
product
})
:
super
(
key:
key
,
product:
product
);
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
...
@@ -180,8 +180,8 @@ class ProductPriceItem extends PriceItem {
...
@@ -180,8 +180,8 @@ class ProductPriceItem extends PriceItem {
}
}
}
}
class
FeaturePriceItem
extends
PriceItem
{
class
_FeaturePriceItem
extends
_
PriceItem
{
FeaturePriceItem
({
Key
key
,
Product
product
})
:
super
(
key:
key
,
product:
product
);
_
FeaturePriceItem
({
Key
key
,
Product
product
})
:
super
(
key:
key
,
product:
product
);
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
...
@@ -193,34 +193,54 @@ class FeaturePriceItem extends PriceItem {
...
@@ -193,34 +193,54 @@ class FeaturePriceItem extends PriceItem {
}
}
}
}
/// Layout the main left and right elements of a FeatureItem.
class
_HeadingLayout
extends
MultiChildLayoutDelegate
{
class
FeatureLayout
extends
MultiChildLayoutDelegate
{
_HeadingLayout
();
FeatureLayout
();
static
final
String
left
=
'left'
;
static
final
String
price
=
'price'
;
static
final
String
right
=
'right'
;
static
final
String
image
=
'image'
;
static
final
String
title
=
'title'
;
static
final
String
description
=
'description'
;
static
final
String
vendor
=
'vendor'
;
// Horizontally: the feature product image appears on the left and
// occupies 50% of the available width; the feature product's
// description apepars on the right and occupies 50% of the available
// width + unitSize. The left and right widgets overlap and the right
// widget is stacked on top.
@override
@override
void
performLayout
(
Size
size
)
{
void
performLayout
(
Size
size
)
{
final
Size
priceSize
=
layoutChild
(
price
,
new
BoxConstraints
.
loose
(
size
));
positionChild
(
price
,
new
Offset
(
size
.
width
-
priceSize
.
width
,
0.0
));
final
double
halfWidth
=
size
.
width
/
2.0
;
final
double
halfWidth
=
size
.
width
/
2.0
;
layoutChild
(
left
,
new
BoxConstraints
.
tightFor
(
width:
halfWidth
,
height:
size
.
height
));
final
double
halfHeight
=
size
.
height
/
2.0
;
positionChild
(
left
,
Offset
.
zero
);
final
double
halfUnit
=
unitSize
/
2.0
;
layoutChild
(
right
,
new
BoxConstraints
.
expand
(
width:
halfWidth
+
unitSize
,
height:
size
.
height
));
const
double
margin
=
16.0
;
positionChild
(
right
,
new
Offset
(
halfWidth
-
unitSize
,
0.0
));
final
Size
imageSize
=
layoutChild
(
image
,
new
BoxConstraints
.
loose
(
size
));
final
double
imageX
=
imageSize
.
width
<
halfWidth
-
halfUnit
?
halfWidth
/
2.0
-
imageSize
.
width
/
2.0
-
halfUnit
:
halfWidth
-
imageSize
.
width
;
positionChild
(
image
,
new
Offset
(
imageX
,
halfHeight
-
imageSize
.
height
/
2.0
));
final
double
maxTitleWidth
=
halfWidth
+
unitSize
-
margin
;
final
BoxConstraints
titleBoxConstraints
=
new
BoxConstraints
(
maxWidth:
maxTitleWidth
);
final
Size
titleSize
=
layoutChild
(
title
,
titleBoxConstraints
);
final
double
titleX
=
halfWidth
-
unitSize
;
final
double
titleY
=
halfHeight
-
titleSize
.
height
;
positionChild
(
title
,
new
Offset
(
titleX
,
titleY
));
final
Size
descriptionSize
=
layoutChild
(
description
,
titleBoxConstraints
);
final
double
descriptionY
=
titleY
+
titleSize
.
height
+
margin
;
positionChild
(
description
,
new
Offset
(
titleX
,
descriptionY
));
layoutChild
(
vendor
,
titleBoxConstraints
);
final
double
vendorY
=
descriptionY
+
descriptionSize
.
height
+
margin
;
positionChild
(
vendor
,
new
Offset
(
titleX
,
vendorY
));
}
}
@override
@override
bool
shouldRelayout
(
Feature
Layout
oldDelegate
)
=>
false
;
bool
shouldRelayout
(
_Heading
Layout
oldDelegate
)
=>
false
;
}
}
//
/
A card that highlights the "featured" catalog item.
// A card that highlights the "featured" catalog item.
class
FeatureItem
extends
StatelessWidget
{
class
_Heading
extends
StatelessWidget
{
FeatureItem
({
Key
key
,
this
.
product
})
:
super
(
key:
key
)
{
_Heading
({
Key
key
,
this
.
product
})
:
super
(
key:
key
)
{
assert
(
product
.
featureTitle
!=
null
);
assert
(
product
.
featureTitle
!=
null
);
assert
(
product
.
featureDescription
!=
null
);
assert
(
product
.
featureDescription
!=
null
);
}
}
...
@@ -229,63 +249,39 @@ class FeatureItem extends StatelessWidget {
...
@@ -229,63 +249,39 @@ class FeatureItem extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
Size
screenSize
=
MediaQuery
.
of
(
context
).
size
;
final
ShrineTheme
theme
=
ShrineTheme
.
of
(
context
);
final
ShrineTheme
theme
=
ShrineTheme
.
of
(
context
);
return
new
AspectRatio
(
return
new
SizedBox
(
aspectRatio:
3.0
/
3.5
,
height:
screenSize
.
width
>
screenSize
.
height
?
(
screenSize
.
height
-
kToolbarHeight
)
*
0.85
:
(
screenSize
.
height
-
kToolbarHeight
)
*
0.70
,
child:
new
Container
(
child:
new
Container
(
decoration:
new
BoxDecoration
(
decoration:
new
BoxDecoration
(
backgroundColor:
theme
.
cardBackgroundColor
,
backgroundColor:
theme
.
cardBackgroundColor
,
border:
new
Border
(
bottom:
new
BorderSide
(
color:
theme
.
dividerColor
)),
border:
new
Border
(
bottom:
new
BorderSide
(
color:
theme
.
dividerColor
)),
),
),
child:
new
C
olumn
(
child:
new
C
ustomMultiChildLayout
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
delegate:
new
_HeadingLayout
()
,
children:
<
Widget
>[
children:
<
Widget
>[
new
SizedBox
(
new
LayoutId
(
height:
unitSize
,
id:
_HeadingLayout
.
price
,
child:
new
Align
(
child:
new
_FeaturePriceItem
(
product:
product
),
alignment:
FractionalOffset
.
topRight
,
child:
new
FeaturePriceItem
(
product:
product
),
),
),
),
new
Expanded
(
new
LayoutId
(
child:
new
CustomMultiChildLayout
(
id:
_HeadingLayout
.
image
,
delegate:
new
FeatureLayout
(),
child:
new
Image
.
asset
(
product
.
imageAsset
,
fit:
BoxFit
.
cover
),
children:
<
Widget
>[
),
new
LayoutId
(
new
LayoutId
(
id:
FeatureLayout
.
left
,
id:
_HeadingLayout
.
title
,
child:
new
ClipRect
(
child:
new
Text
(
product
.
featureTitle
,
style:
theme
.
featureTitleStyle
),
child:
new
OverflowBox
(
),
minWidth:
340.0
,
new
LayoutId
(
maxWidth:
340.0
,
id:
_HeadingLayout
.
description
,
minHeight:
340.0
,
child:
new
Text
(
product
.
featureDescription
,
style:
theme
.
featureStyle
),
maxHeight:
340.0
,
),
alignment:
FractionalOffset
.
topRight
,
new
LayoutId
(
child:
new
Image
.
asset
(
product
.
imageAsset
,
fit:
BoxFit
.
cover
),
id:
_HeadingLayout
.
vendor
,
),
child:
new
_VendorItem
(
vendor:
product
.
vendor
),
),
),
new
LayoutId
(
id:
FeatureLayout
.
right
,
child:
new
Padding
(
padding:
const
EdgeInsets
.
only
(
right:
16.0
),
child:
new
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
new
Padding
(
padding:
const
EdgeInsets
.
only
(
top:
18.0
),
child:
new
Text
(
product
.
featureTitle
,
style:
theme
.
featureTitleStyle
),
),
new
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
16.0
),
child:
new
Text
(
product
.
featureDescription
,
style:
theme
.
featureStyle
),
),
new
VendorItem
(
vendor:
product
.
vendor
),
],
),
),
),
],
),
),
),
],
],
),
),
...
@@ -294,9 +290,10 @@ class FeatureItem extends StatelessWidget {
...
@@ -294,9 +290,10 @@ class FeatureItem extends StatelessWidget {
}
}
}
}
/// A card that displays a product's image, price, and vendor.
// A card that displays a product's image, price, and vendor. The _ProductItem
class
ProductItem
extends
StatelessWidget
{
// cards appear in a grid below the heading.
ProductItem
({
Key
key
,
this
.
product
,
this
.
onPressed
})
:
super
(
key:
key
)
{
class
_ProductItem
extends
StatelessWidget
{
_ProductItem
({
Key
key
,
this
.
product
,
this
.
onPressed
})
:
super
(
key:
key
)
{
assert
(
product
!=
null
);
assert
(
product
!=
null
);
}
}
...
@@ -312,7 +309,7 @@ class ProductItem extends StatelessWidget {
...
@@ -312,7 +309,7 @@ class ProductItem extends StatelessWidget {
children:
<
Widget
>[
children:
<
Widget
>[
new
Align
(
new
Align
(
alignment:
FractionalOffset
.
centerRight
,
alignment:
FractionalOffset
.
centerRight
,
child:
new
ProductPriceItem
(
product:
product
),
child:
new
_
ProductPriceItem
(
product:
product
),
),
),
new
Container
(
new
Container
(
width:
144.0
,
width:
144.0
,
...
@@ -325,7 +322,7 @@ class ProductItem extends StatelessWidget {
...
@@ -325,7 +322,7 @@ class ProductItem extends StatelessWidget {
),
),
new
Padding
(
new
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8.0
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8.0
),
child:
new
VendorItem
(
vendor:
product
.
vendor
),
child:
new
_
VendorItem
(
vendor:
product
.
vendor
),
),
),
],
],
),
),
...
@@ -339,18 +336,18 @@ class ProductItem extends StatelessWidget {
...
@@ -339,18 +336,18 @@ class ProductItem extends StatelessWidget {
}
}
}
}
//
/ The Shrine app's home page. Displays the featured item above all of the
//
The Shrine app's home page. Displays the featured item above a grid
//
/ product items arranged in two column
s.
//
of the product item
s.
class
ShrineHome
extends
StatefulWidget
{
class
ShrineHome
extends
StatefulWidget
{
@override
@override
_ShrineHomeState
createState
()
=>
new
_ShrineHomeState
();
_ShrineHomeState
createState
()
=>
new
_ShrineHomeState
();
}
}
class
_ShrineHomeState
extends
State
<
ShrineHome
>
{
class
_ShrineHomeState
extends
State
<
ShrineHome
>
{
static
final
GlobalKey
<
ScaffoldState
>
scaffoldKey
=
new
GlobalKey
<
ScaffoldState
>(
debugLabel:
'Shrine Home'
);
static
final
GlobalKey
<
ScaffoldState
>
_
scaffoldKey
=
new
GlobalKey
<
ScaffoldState
>(
debugLabel:
'Shrine Home'
);
static
final
ShrineGridDelegate
gridDelegate
=
new
ShrineGridDelegate
();
static
final
_ShrineGridDelegate
gridDelegate
=
new
_
ShrineGridDelegate
();
Future
<
Null
>
showOrderPage
(
Product
product
)
async
{
Future
<
Null
>
_
showOrderPage
(
Product
product
)
async
{
final
Order
order
=
_shoppingCart
[
product
]
??
new
Order
(
product:
product
);
final
Order
order
=
_shoppingCart
[
product
]
??
new
Order
(
product:
product
);
final
Order
completedOrder
=
await
Navigator
.
push
(
context
,
new
ShrineOrderRoute
(
final
Order
completedOrder
=
await
Navigator
.
push
(
context
,
new
ShrineOrderRoute
(
order:
order
,
order:
order
,
...
@@ -371,13 +368,13 @@ class _ShrineHomeState extends State<ShrineHome> {
...
@@ -371,13 +368,13 @@ class _ShrineHomeState extends State<ShrineHome> {
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
Product
featured
=
_products
.
firstWhere
((
Product
product
)
=>
product
.
featureDescription
!=
null
);
final
Product
featured
=
_products
.
firstWhere
((
Product
product
)
=>
product
.
featureDescription
!=
null
);
return
new
ShrinePage
(
return
new
ShrinePage
(
scaffoldKey:
scaffoldKey
,
scaffoldKey:
_
scaffoldKey
,
products:
_products
,
products:
_products
,
shoppingCart:
_shoppingCart
,
shoppingCart:
_shoppingCart
,
body:
new
CustomScrollView
(
body:
new
CustomScrollView
(
slivers:
<
Widget
>[
slivers:
<
Widget
>[
new
SliverToBoxAdapter
(
new
SliverToBoxAdapter
(
child:
new
FeatureItem
(
product:
featured
),
child:
new
_Heading
(
product:
featured
),
),
),
new
SliverPadding
(
new
SliverPadding
(
padding:
const
EdgeInsets
.
all
(
16.0
),
padding:
const
EdgeInsets
.
all
(
16.0
),
...
@@ -385,9 +382,9 @@ class _ShrineHomeState extends State<ShrineHome> {
...
@@ -385,9 +382,9 @@ class _ShrineHomeState extends State<ShrineHome> {
gridDelegate:
gridDelegate
,
gridDelegate:
gridDelegate
,
delegate:
new
SliverChildListDelegate
(
delegate:
new
SliverChildListDelegate
(
_products
.
map
((
Product
product
)
{
_products
.
map
((
Product
product
)
{
return
new
ProductItem
(
return
new
_
ProductItem
(
product:
product
,
product:
product
,
onPressed:
()
{
showOrderPage
(
product
);
},
onPressed:
()
{
_
showOrderPage
(
product
);
},
);
);
}).
toList
(),
}).
toList
(),
),
),
...
...
examples/flutter_gallery/lib/demo/shrine/shrine_order.dart
View file @
9192f672
...
@@ -9,10 +9,133 @@ import 'shrine_page.dart';
...
@@ -9,10 +9,133 @@ import 'shrine_page.dart';
import
'shrine_theme.dart'
;
import
'shrine_theme.dart'
;
import
'shrine_types.dart'
;
import
'shrine_types.dart'
;
/// Describes a product and vendor in detail, supports specifying
// Displays the product title's, description, and order quantity dropdown.
/// a order quantity (0-5). Appears at the top of the OrderPage.
class
_ProductItem
extends
StatelessWidget
{
class
OrderItem
extends
StatelessWidget
{
_ProductItem
({
Key
key
,
this
.
product
,
this
.
quantity
,
this
.
onChanged
})
:
super
(
key:
key
)
{
OrderItem
({
Key
key
,
this
.
product
,
this
.
quantity
,
this
.
quantityChanged
})
:
super
(
key:
key
)
{
assert
(
product
!=
null
);
assert
(
quantity
!=
null
);
assert
(
onChanged
!=
null
);
}
final
Product
product
;
final
int
quantity
;
final
ValueChanged
<
int
>
onChanged
;
@override
Widget
build
(
BuildContext
context
)
{
final
ShrineTheme
theme
=
ShrineTheme
.
of
(
context
);
return
new
Column
(
mainAxisSize:
MainAxisSize
.
min
,
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
new
Text
(
product
.
name
,
style:
theme
.
featureTitleStyle
),
const
SizedBox
(
height:
24.0
),
new
Text
(
product
.
description
,
style:
theme
.
featureStyle
),
const
SizedBox
(
height:
16.0
),
new
Padding
(
padding:
const
EdgeInsets
.
only
(
top:
8.0
,
bottom:
8.0
,
right:
88.0
),
child:
new
DropdownButtonHideUnderline
(
child:
new
Container
(
decoration:
new
BoxDecoration
(
border:
new
Border
.
all
(
color:
const
Color
(
0xFFD9D9D9
),
),
),
child:
new
DropdownButton
<
int
>(
items:
<
int
>[
0
,
1
,
2
,
3
,
4
,
5
].
map
((
int
value
)
{
return
new
DropdownMenuItem
<
int
>(
value:
value
,
child:
new
Padding
(
padding:
const
EdgeInsets
.
only
(
left:
8.0
),
child:
new
Text
(
'Quantity
$value
'
,
style:
theme
.
quantityMenuStyle
),
),
);
}).
toList
(),
value:
quantity
,
onChanged:
onChanged
,
),
),
),
),
],
);
}
}
// Vendor name and description
class
_VendorItem
extends
StatelessWidget
{
_VendorItem
({
Key
key
,
this
.
vendor
})
:
super
(
key:
key
)
{
assert
(
vendor
!=
null
);
}
final
Vendor
vendor
;
@override
Widget
build
(
BuildContext
context
)
{
final
ShrineTheme
theme
=
ShrineTheme
.
of
(
context
);
return
new
Column
(
mainAxisSize:
MainAxisSize
.
min
,
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
new
SizedBox
(
height:
24.0
,
child:
new
Align
(
alignment:
FractionalOffset
.
bottomLeft
,
child:
new
Text
(
vendor
.
name
,
style:
theme
.
vendorTitleStyle
),
),
),
const
SizedBox
(
height:
16.0
),
new
Text
(
vendor
.
description
,
style:
theme
.
vendorStyle
),
],
);
}
}
// Layout the order page's heading: the product's image, the
// title/description/dropdown product item, and the vendor item.
class
_HeadingLayout
extends
MultiChildLayoutDelegate
{
_HeadingLayout
();
static
final
String
image
=
'image'
;
static
final
String
icon
=
'icon'
;
static
final
String
product
=
'product'
;
static
final
String
vendor
=
'vendor'
;
@override
void
performLayout
(
Size
size
)
{
const
double
margin
=
56.0
;
final
bool
landscape
=
size
.
width
>
size
.
height
;
final
double
imageWidth
=
(
landscape
?
size
.
width
/
2.0
:
size
.
width
)
-
margin
*
2.0
;
final
BoxConstraints
imageConstraints
=
new
BoxConstraints
(
maxHeight:
224.0
,
maxWidth:
imageWidth
);
final
Size
imageSize
=
layoutChild
(
image
,
imageConstraints
);
final
double
imageY
=
0.0
;
positionChild
(
image
,
new
Offset
(
margin
,
imageY
));
final
double
productWidth
=
landscape
?
size
.
width
/
2.0
:
size
.
width
-
margin
;
final
BoxConstraints
productConstraints
=
new
BoxConstraints
(
maxWidth:
productWidth
);
final
Size
productSize
=
layoutChild
(
product
,
productConstraints
);
final
double
productX
=
landscape
?
size
.
width
/
2.0
:
margin
;
final
double
productY
=
landscape
?
0.0
:
imageY
+
imageSize
.
height
+
16.0
;
positionChild
(
product
,
new
Offset
(
productX
,
productY
));
final
Size
iconSize
=
layoutChild
(
icon
,
new
BoxConstraints
.
loose
(
size
));
positionChild
(
icon
,
new
Offset
(
productX
-
iconSize
.
width
-
16.0
,
productY
+
8.0
));
final
double
vendorWidth
=
landscape
?
size
.
width
-
margin
:
productWidth
;
layoutChild
(
vendor
,
new
BoxConstraints
(
maxWidth:
vendorWidth
));
final
double
vendorX
=
landscape
?
margin
:
productX
;
final
double
vendorY
=
productY
+
productSize
.
height
+
16.0
;
positionChild
(
vendor
,
new
Offset
(
vendorX
,
vendorY
));
}
@override
bool
shouldRelayout
(
_HeadingLayout
oldDelegate
)
=>
true
;
}
// Describes a product and vendor in detail, supports specifying
// a order quantity (0-5). Appears at the top of the OrderPage.
class
_Heading
extends
StatelessWidget
{
_Heading
({
Key
key
,
this
.
product
,
this
.
quantity
,
this
.
quantityChanged
})
:
super
(
key:
key
)
{
assert
(
product
!=
null
);
assert
(
product
!=
null
);
assert
(
quantity
!=
null
&&
quantity
>=
0
&&
quantity
<=
5
);
assert
(
quantity
!=
null
&&
quantity
>=
0
&&
quantity
<=
5
);
}
}
...
@@ -23,92 +146,50 @@ class OrderItem extends StatelessWidget {
...
@@ -23,92 +146,50 @@ class OrderItem extends StatelessWidget {
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
final
ShrineTheme
theme
=
ShrineTheme
.
of
(
context
);
final
Size
screenSize
=
MediaQuery
.
of
(
context
).
size
;
return
new
Material
(
return
new
SizedBox
(
type:
MaterialType
.
card
,
height:
(
screenSize
.
height
-
kToolbarHeight
)
*
1.35
,
elevation:
0
,
child:
new
Material
(
child:
new
Padding
(
type:
MaterialType
.
card
,
padding:
const
EdgeInsets
.
only
(
left:
16.0
,
top:
18.0
,
right:
16.0
,
bottom:
24.0
),
elevation:
0
,
child:
new
Column
(
child:
new
Padding
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
padding:
const
EdgeInsets
.
only
(
left:
16.0
,
top:
18.0
,
right:
16.0
,
bottom:
24.0
),
children:
<
Widget
>[
child:
new
CustomMultiChildLayout
(
new
Padding
(
delegate:
new
_HeadingLayout
(),
padding:
const
EdgeInsets
.
only
(
left:
56.0
),
children:
<
Widget
>[
child:
new
SizedBox
(
new
LayoutId
(
width:
248.0
,
id:
_HeadingLayout
.
image
,
height:
248.0
,
child:
new
Hero
(
child:
new
Hero
(
tag:
product
.
tag
,
tag:
product
.
tag
,
child:
new
Image
.
asset
(
product
.
imageAsset
,
fit:
BoxFit
.
contain
),
child:
new
Image
.
asset
(
product
.
imageAsset
,
fit:
BoxFit
.
contain
,
alignment:
FractionalOffset
.
center
,
),
),
),
),
),
),
new
LayoutId
(
const
SizedBox
(
height:
24.0
),
id:
_HeadingLayout
.
icon
,
new
Row
(
child:
new
Icon
(
children:
<
Widget
>[
Icons
.
info_outline
,
new
Padding
(
size:
24.0
,
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16.0
),
color:
const
Color
(
0xFFFFE0E0
),
child:
new
Center
(
child:
new
Icon
(
Icons
.
info_outline
,
size:
24.0
,
color:
const
Color
(
0xFFFFE0E0
),
),
),
),
),
new
Expanded
(
),
child:
new
Text
(
product
.
name
,
style:
theme
.
featureTitleStyle
),
new
LayoutId
(
id:
_HeadingLayout
.
product
,
child:
new
_ProductItem
(
product:
product
,
quantity:
quantity
,
onChanged:
quantityChanged
,
),
),
],
),
new
Padding
(
padding:
const
EdgeInsets
.
only
(
left:
56.0
),
child:
new
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
const
SizedBox
(
height:
24.0
),
new
Text
(
product
.
description
,
style:
theme
.
featureStyle
),
const
SizedBox
(
height:
16.0
),
new
Padding
(
padding:
const
EdgeInsets
.
only
(
top:
8.0
,
bottom:
8.0
,
right:
88.0
),
child:
new
DropdownButtonHideUnderline
(
child:
new
Container
(
decoration:
new
BoxDecoration
(
border:
new
Border
.
all
(
color:
const
Color
(
0xFFD9D9D9
),
),
),
child:
new
DropdownButton
<
int
>(
items:
<
int
>[
0
,
1
,
2
,
3
,
4
,
5
].
map
((
int
value
)
{
return
new
DropdownMenuItem
<
int
>(
value:
value
,
child:
new
Padding
(
padding:
const
EdgeInsets
.
only
(
left:
8.0
),
child:
new
Text
(
'Quantity
$value
'
,
style:
theme
.
quantityMenuStyle
),
),
);
}).
toList
(),
value:
quantity
,
onChanged:
quantityChanged
,
),
),
),
),
const
SizedBox
(
height:
16.0
),
new
SizedBox
(
height:
24.0
,
child:
new
Align
(
alignment:
FractionalOffset
.
bottomLeft
,
child:
new
Text
(
product
.
vendor
.
name
,
style:
theme
.
vendorTitleStyle
),
),
),
const
SizedBox
(
height:
16.0
),
new
Text
(
product
.
vendor
.
description
,
style:
theme
.
vendorStyle
),
const
SizedBox
(
height:
24.0
),
],
),
),
),
new
LayoutId
(
],
id:
_HeadingLayout
.
vendor
,
child:
new
_VendorItem
(
vendor:
product
.
vendor
),
),
],
),
),
),
),
),
);
);
...
@@ -130,9 +211,9 @@ class OrderPage extends StatefulWidget {
...
@@ -130,9 +211,9 @@ class OrderPage extends StatefulWidget {
_OrderPageState
createState
()
=>
new
_OrderPageState
();
_OrderPageState
createState
()
=>
new
_OrderPageState
();
}
}
//
/ Displays a product's OrderItem
above photos of all of the other products
//
Displays a product's heading
above photos of all of the other products
//
/
arranged in two columns. Enables the user to specify a quantity and add an
// arranged in two columns. Enables the user to specify a quantity and add an
//
/
order to the shopping cart.
// order to the shopping cart.
class
_OrderPageState
extends
State
<
OrderPage
>
{
class
_OrderPageState
extends
State
<
OrderPage
>
{
GlobalKey
<
ScaffoldState
>
scaffoldKey
;
GlobalKey
<
ScaffoldState
>
scaffoldKey
;
...
@@ -185,24 +266,20 @@ class _OrderPageState extends State<OrderPage> {
...
@@ -185,24 +266,20 @@ class _OrderPageState extends State<OrderPage> {
),
),
body:
new
CustomScrollView
(
body:
new
CustomScrollView
(
slivers:
<
Widget
>[
slivers:
<
Widget
>[
new
SliverList
(
new
SliverToBoxAdapter
(
delegate:
new
SliverChildListDelegate
(<
Widget
>[
child:
new
_Heading
(
new
OrderItem
(
product:
config
.
order
.
product
,
product:
config
.
order
.
product
,
quantity:
currentOrder
.
quantity
,
quantity:
currentOrder
.
quantity
,
quantityChanged:
(
int
value
)
{
updateOrder
(
quantity:
value
);
},
quantityChanged:
(
int
value
)
{
updateOrder
(
quantity:
value
);
},
),
),
const
SizedBox
(
height:
24.0
),
]),
),
),
new
SliverPadding
(
new
SliverPadding
(
padding:
const
EdgeInsets
.
all
(
8.0
),
padding:
const
EdgeInsets
.
fromLTRB
(
8.0
,
32.0
,
8.0
,
8.0
),
sliver:
new
SliverGrid
(
sliver:
new
SliverGrid
(
gridDelegate:
const
SliverGridDelegateWith
FixedCrossAxisCou
nt
(
gridDelegate:
const
SliverGridDelegateWith
MaxCrossAxisExte
nt
(
crossAxisCount:
2
,
maxCrossAxisExtent:
248.0
,
mainAxisSpacing:
8.0
,
mainAxisSpacing:
8.0
,
crossAxisSpacing:
8.0
,
crossAxisSpacing:
8.0
,
childAspectRatio:
160.0
/
216.0
,
// width/height
),
),
delegate:
new
SliverChildListDelegate
(
delegate:
new
SliverChildListDelegate
(
config
.
products
config
.
products
...
@@ -225,11 +302,11 @@ class _OrderPageState extends State<OrderPage> {
...
@@ -225,11 +302,11 @@ class _OrderPageState extends State<OrderPage> {
}
}
}
}
//
/
Displays a full-screen modal OrderPage.
// Displays a full-screen modal OrderPage.
//
/
//
//
/
The order field will be replaced each time the user reconfigures the order.
// The order field will be replaced each time the user reconfigures the order.
//
/
When the user backs out of this route the completer's value will be the
// When the user backs out of this route the completer's value will be the
//
/
final value of the order field.
// final value of the order field.
class
ShrineOrderRoute
extends
ShrinePageRoute
<
Order
>
{
class
ShrineOrderRoute
extends
ShrinePageRoute
<
Order
>
{
ShrineOrderRoute
({
ShrineOrderRoute
({
this
.
order
,
this
.
order
,
...
...
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