Unverified Commit d8bfb3a9 authored by Chris Bracken's avatar Chris Bracken Committed by GitHub

Apply media padding to Gallery Material Design demos (#13593)

Applies media padding (e.g. iPhone X safe area insets) to the Material Design demos in the Gallery.

Covers the following demos:
* Buttons (via the TabbedComponentDemoScaffold change)
* Cards
* Expansion panels
* Grid list
* Icons
* Images (via the TabbedComponentDemoScaffold change)
* Page Selector
* Progress Indicator
* Scrollable tabs
* Selection controls (via the TabbedComponentDemoScaffold change)
* Snack bar
* Tabs
* Text fields
* Tooltips

Fixes #13594
parent d9edab84
......@@ -60,85 +60,89 @@ class TravelDestinationItem extends StatelessWidget {
final TextStyle titleStyle = theme.textTheme.headline.copyWith(color: Colors.white);
final TextStyle descriptionStyle = theme.textTheme.subhead;
return new Container(
padding: const EdgeInsets.all(8.0),
height: height,
child: new Card(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// photo and title
new SizedBox(
height: 184.0,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new Image.asset(
destination.assetName,
package: destination.assetPackage,
fit: BoxFit.cover,
return new SafeArea(
top: false,
bottom: false,
child: new Container(
padding: const EdgeInsets.all(8.0),
height: height,
child: new Card(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// photo and title
new SizedBox(
height: 184.0,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new Image.asset(
destination.assetName,
package: destination.assetPackage,
fit: BoxFit.cover,
),
),
),
new Positioned(
bottom: 16.0,
left: 16.0,
right: 16.0,
child: new FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft,
child: new Text(destination.title,
style: titleStyle,
new Positioned(
bottom: 16.0,
left: 16.0,
right: 16.0,
child: new FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft,
child: new Text(destination.title,
style: titleStyle,
),
),
),
),
],
],
),
),
),
// description and share/expore buttons
new Expanded(
child: new Padding(
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
child: new DefaultTextStyle(
softWrap: false,
overflow: TextOverflow.ellipsis,
style: descriptionStyle,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// three line description
new Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: new Text(
destination.description[0],
style: descriptionStyle.copyWith(color: Colors.black54),
// description and share/expore buttons
new Expanded(
child: new Padding(
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
child: new DefaultTextStyle(
softWrap: false,
overflow: TextOverflow.ellipsis,
style: descriptionStyle,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// three line description
new Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: new Text(
destination.description[0],
style: descriptionStyle.copyWith(color: Colors.black54),
),
),
),
new Text(destination.description[1]),
new Text(destination.description[2]),
],
new Text(destination.description[1]),
new Text(destination.description[2]),
],
),
),
),
),
),
// share, explore buttons
new ButtonTheme.bar(
child: new ButtonBar(
alignment: MainAxisAlignment.start,
children: <Widget>[
new FlatButton(
child: const Text('SHARE'),
textColor: Colors.amber.shade500,
onPressed: () { /* do nothing */ },
),
new FlatButton(
child: const Text('EXPLORE'),
textColor: Colors.amber.shade500,
onPressed: () { /* do nothing */ },
),
],
// share, explore buttons
new ButtonTheme.bar(
child: new ButtonBar(
alignment: MainAxisAlignment.start,
children: <Widget>[
new FlatButton(
child: const Text('SHARE'),
textColor: Colors.amber.shade500,
onPressed: () { /* do nothing */ },
),
new FlatButton(
child: const Text('EXPLORE'),
textColor: Colors.amber.shade500,
onPressed: () { /* do nothing */ },
),
],
),
),
),
],
],
),
),
),
);
......
......@@ -131,74 +131,78 @@ class _DateAndTimePickerDemoState extends State<DateAndTimePickerDemo> {
return new Scaffold(
appBar: new AppBar(title: const Text('Date and time pickers')),
body: new DropdownButtonHideUnderline(
child: new ListView(
padding: const EdgeInsets.all(16.0),
children: <Widget>[
new TextField(
decoration: const InputDecoration(
labelText: 'Event name',
child: new SafeArea(
top: false,
bottom: false,
child: new ListView(
padding: const EdgeInsets.all(16.0),
children: <Widget>[
new TextField(
decoration: const InputDecoration(
labelText: 'Event name',
),
style: Theme.of(context).textTheme.display1,
),
style: Theme.of(context).textTheme.display1,
),
new TextField(
decoration: const InputDecoration(
labelText: 'Location',
new TextField(
decoration: const InputDecoration(
labelText: 'Location',
),
style: Theme.of(context).textTheme.display1.copyWith(fontSize: 20.0),
),
style: Theme.of(context).textTheme.display1.copyWith(fontSize: 20.0),
),
new _DateTimePicker(
labelText: 'From',
selectedDate: _fromDate,
selectedTime: _fromTime,
selectDate: (DateTime date) {
setState(() {
_fromDate = date;
});
},
selectTime: (TimeOfDay time) {
setState(() {
_fromTime = time;
});
},
),
new _DateTimePicker(
labelText: 'To',
selectedDate: _toDate,
selectedTime: _toTime,
selectDate: (DateTime date) {
setState(() {
_toDate = date;
});
},
selectTime: (TimeOfDay time) {
setState(() {
_toTime = time;
});
},
),
new InputDecorator(
decoration: const InputDecoration(
labelText: 'Activity',
hintText: 'Choose an activity',
new _DateTimePicker(
labelText: 'From',
selectedDate: _fromDate,
selectedTime: _fromTime,
selectDate: (DateTime date) {
setState(() {
_fromDate = date;
});
},
selectTime: (TimeOfDay time) {
setState(() {
_fromTime = time;
});
},
),
isEmpty: _activity == null,
child: new DropdownButton<String>(
value: _activity,
isDense: true,
onChanged: (String newValue) {
new _DateTimePicker(
labelText: 'To',
selectedDate: _toDate,
selectedTime: _toTime,
selectDate: (DateTime date) {
setState(() {
_toDate = date;
});
},
selectTime: (TimeOfDay time) {
setState(() {
_activity = newValue;
_toTime = time;
});
},
items: _allActivities.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
),
),
],
new InputDecorator(
decoration: const InputDecoration(
labelText: 'Activity',
hintText: 'Choose an activity',
),
isEmpty: _activity == null,
child: new DropdownButton<String>(
value: _activity,
isDense: true,
onChanged: (String newValue) {
setState(() {
_activity = newValue;
});
},
items: _allActivities.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList(),
),
),
],
),
),
),
);
......
......@@ -336,24 +336,28 @@ class _ExpansionPanelsDemoState extends State<ExpasionPanelsDemo> {
return new Scaffold(
appBar: new AppBar(title: const Text('Expansion panels')),
body: new SingleChildScrollView(
child: new Container(
margin: const EdgeInsets.all(24.0),
child: new ExpansionPanelList(
expansionCallback: (int index, bool isExpanded) {
setState(() {
_demoItems[index].isExpanded = !isExpanded;
});
},
children: _demoItems.map((DemoItem<dynamic> item) {
return new ExpansionPanel(
isExpanded: item.isExpanded,
headerBuilder: item.headerBuilder,
body: item.builder(item)
);
}).toList()
)
)
)
child: new SafeArea(
top: false,
bottom: false,
child: new Container(
margin: const EdgeInsets.all(24.0),
child: new ExpansionPanelList(
expansionCallback: (int index, bool isExpanded) {
setState(() {
_demoItems[index].isExpanded = !isExpanded;
});
},
children: _demoItems.map((DemoItem<dynamic> item) {
return new ExpansionPanel(
isExpanded: item.isExpanded,
headerBuilder: item.headerBuilder,
body: item.builder(item)
);
}).toList()
),
),
),
),
);
}
}
......@@ -363,27 +363,31 @@ class GridListDemoState extends State<GridListDemo> {
body: new Column(
children: <Widget>[
new Expanded(
child: new GridView.count(
crossAxisCount: (orientation == Orientation.portrait) ? 2 : 3,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
padding: const EdgeInsets.all(4.0),
childAspectRatio: (orientation == Orientation.portrait) ? 1.0 : 1.3,
children: photos.map((Photo photo) {
return new GridDemoPhotoItem(
photo: photo,
tileStyle: _tileStyle,
onBannerTap: (Photo photo) {
setState(() {
photo.isFavorite = !photo.isFavorite;
});
}
);
}).toList(),
)
)
]
)
child: new SafeArea(
top: false,
bottom: false,
child: new GridView.count(
crossAxisCount: (orientation == Orientation.portrait) ? 2 : 3,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
padding: const EdgeInsets.all(4.0),
childAspectRatio: (orientation == Orientation.portrait) ? 1.0 : 1.3,
children: photos.map((Photo photo) {
return new GridDemoPhotoItem(
photo: photo,
tileStyle: _tileStyle,
onBannerTap: (Photo photo) {
setState(() {
photo.isFavorite = !photo.isFavorite;
});
}
);
}).toList(),
),
),
),
],
),
);
}
}
......@@ -54,10 +54,14 @@ class IconsDemoState extends State<IconsDemo> {
data: new IconThemeData(color: iconColor),
child: new Padding(
padding: const EdgeInsets.all(24.0),
child: new Column(
children: <Widget>[
new _IconsDemoCard(handleIconButtonPress),
],
child: new SafeArea(
top: false,
bottom: false,
child: new Column(
children: <Widget>[
new _IconsDemoCard(handleIconButtonPress),
],
),
),
),
),
......
......@@ -19,45 +19,49 @@ class _PageSelector extends StatelessWidget {
Widget build(BuildContext context) {
final TabController controller = DefaultTabController.of(context);
final Color color = Theme.of(context).accentColor;
return new Column(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 16.0),
child: new Row(
children: <Widget>[
new IconButton(
icon: const Icon(Icons.chevron_left),
color: color,
onPressed: () { _handleArrowButtonPress(context, -1); },
tooltip: 'Page back'
),
new TabPageSelector(controller: controller),
new IconButton(
icon: const Icon(Icons.chevron_right),
color: color,
onPressed: () { _handleArrowButtonPress(context, 1); },
tooltip: 'Page forward'
)
],
mainAxisAlignment: MainAxisAlignment.spaceBetween
)
),
new Expanded(
child: new TabBarView(
children: icons.map((IconData icon) {
return new Container(
key: new ObjectKey(icon),
padding: const EdgeInsets.all(12.0),
child: new Card(
child: new Center(
child: new Icon(icon, size: 128.0, color: color)
),
return new SafeArea(
top: false,
bottom: false,
child: new Column(
children: <Widget>[
new Container(
margin: const EdgeInsets.only(top: 16.0),
child: new Row(
children: <Widget>[
new IconButton(
icon: const Icon(Icons.chevron_left),
color: color,
onPressed: () { _handleArrowButtonPress(context, -1); },
tooltip: 'Page back'
),
);
}).toList()
new TabPageSelector(controller: controller),
new IconButton(
icon: const Icon(Icons.chevron_right),
color: color,
onPressed: () { _handleArrowButtonPress(context, 1); },
tooltip: 'Page forward'
)
],
mainAxisAlignment: MainAxisAlignment.spaceBetween
)
),
new Expanded(
child: new TabBarView(
children: icons.map((IconData icon) {
return new Container(
key: new ObjectKey(icon),
padding: const EdgeInsets.all(12.0),
child: new Card(
child: new Center(
child: new Icon(icon, size: 128.0, color: color)
),
),
);
}).toList()
),
),
),
],
],
),
);
}
}
......
......@@ -107,17 +107,21 @@ class _ProgressIndicatorDemoState extends State<ProgressIndicatorDemo> with Sing
child: new GestureDetector(
onTap: _handleTap,
behavior: HitTestBehavior.opaque,
child: new Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
child: new AnimatedBuilder(
animation: _animation,
builder: _buildIndicators
)
)
)
)
)
)
child: new SafeArea(
top: false,
bottom: false,
child: new Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
child: new AnimatedBuilder(
animation: _animation,
builder: _buildIndicators
),
),
),
),
),
),
),
);
}
}
......@@ -105,15 +105,19 @@ class ScrollableTabsDemoState extends State<ScrollableTabsDemo> with SingleTicke
body: new TabBarView(
controller: _controller,
children: _allPages.map((_Page page) {
return new Container(
key: new ObjectKey(page.icon),
padding: const EdgeInsets.all(12.0),
child:new Card(
child: new Center(
child: new Icon(
page.icon,
color: iconColor,
size: 128.0,
return new SafeArea(
top: false,
bottom: false,
child: new Container(
key: new ObjectKey(page.icon),
padding: const EdgeInsets.all(12.0),
child:new Card(
child: new Center(
child: new Icon(
page.icon,
color: iconColor,
size: 128.0,
),
),
),
),
......
......@@ -29,39 +29,43 @@ class _SnackBarDemoState extends State<SnackBarDemo> {
int _snackBarIndex = 1;
Widget buildBody(BuildContext context) {
return new ListView(
padding: const EdgeInsets.all(24.0),
children: <Widget>[
const Text(_text1),
const Text(_text2),
new Center(
child: new RaisedButton(
child: const Text('SHOW A SNACKBAR'),
onPressed: () {
final int thisSnackBarIndex = _snackBarIndex++;
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('This is snackbar #$thisSnackBarIndex.'),
action: new SnackBarAction(
label: 'ACTION',
onPressed: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('You pressed snackbar $thisSnackBarIndex\'s action.')
));
}
)
));
}
)
),
const Text(_text3),
]
.map((Widget child) {
return new Container(
margin: const EdgeInsets.symmetric(vertical: 12.0),
child: child
);
})
.toList()
return new SafeArea(
top: false,
bottom: false,
child: new ListView(
padding: const EdgeInsets.all(24.0),
children: <Widget>[
const Text(_text1),
const Text(_text2),
new Center(
child: new RaisedButton(
child: const Text('SHOW A SNACKBAR'),
onPressed: () {
final int thisSnackBarIndex = _snackBarIndex++;
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('This is snackbar #$thisSnackBarIndex.'),
action: new SnackBarAction(
label: 'ACTION',
onPressed: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('You pressed snackbar $thisSnackBarIndex\'s action.')
));
}
),
));
}
),
),
const Text(_text3),
]
.map((Widget child) {
return new Container(
margin: const EdgeInsets.symmetric(vertical: 12.0),
child: child
);
})
.toList()
),
);
}
......
......@@ -154,15 +154,19 @@ class TabsDemo extends StatelessWidget {
},
body: new TabBarView(
children: _allPages.keys.map((_Page page) {
return new ListView(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
itemExtent: _CardDataItem.height,
children: _allPages[page].map((_CardData data) {
return new Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: new _CardDataItem(page: page, data: data),
);
}).toList(),
return new SafeArea(
top: false,
bottom: false,
child: new ListView(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
itemExtent: _CardDataItem.height,
children: _allPages[page].map((_CardData data) {
return new Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: new _CardDataItem(page: page, data: data),
);
}).toList(),
),
);
}).toList(),
),
......
......@@ -108,98 +108,102 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
appBar: new AppBar(
title: const Text('Text fields'),
),
body: new Form(
key: _formKey,
autovalidate: _autovalidate,
onWillPop: _warnUserAboutInvalidData,
child: new ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
children: <Widget>[
new TextFormField(
decoration: const InputDecoration(
icon: const Icon(Icons.person),
hintText: 'What do people call you?',
labelText: 'Name *',
body: new SafeArea(
top: false,
bottom: false,
child: new Form(
key: _formKey,
autovalidate: _autovalidate,
onWillPop: _warnUserAboutInvalidData,
child: new ListView(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
children: <Widget>[
new TextFormField(
decoration: const InputDecoration(
icon: const Icon(Icons.person),
hintText: 'What do people call you?',
labelText: 'Name *',
),
onSaved: (String value) { person.name = value; },
validator: _validateName,
),
onSaved: (String value) { person.name = value; },
validator: _validateName,
),
new TextFormField(
decoration: const InputDecoration(
icon: const Icon(Icons.phone),
hintText: 'Where can we reach you?',
labelText: 'Phone Number *',
prefixText: '+1'
new TextFormField(
decoration: const InputDecoration(
icon: const Icon(Icons.phone),
hintText: 'Where can we reach you?',
labelText: 'Phone Number *',
prefixText: '+1'
),
keyboardType: TextInputType.phone,
onSaved: (String value) { person.phoneNumber = value; },
validator: _validatePhoneNumber,
// TextInputFormatters are applied in sequence.
inputFormatters: <TextInputFormatter> [
WhitelistingTextInputFormatter.digitsOnly,
// Fit the validating format.
_phoneNumberFormatter,
],
),
keyboardType: TextInputType.phone,
onSaved: (String value) { person.phoneNumber = value; },
validator: _validatePhoneNumber,
// TextInputFormatters are applied in sequence.
inputFormatters: <TextInputFormatter> [
WhitelistingTextInputFormatter.digitsOnly,
// Fit the validating format.
_phoneNumberFormatter,
],
),
new TextFormField(
decoration: const InputDecoration(
hintText: 'Tell us about yourself',
helperText: 'Keep it short, this is just a demo',
labelText: 'Life story',
new TextFormField(
decoration: const InputDecoration(
hintText: 'Tell us about yourself',
helperText: 'Keep it short, this is just a demo',
labelText: 'Life story',
),
maxLines: 3,
),
maxLines: 3,
),
new TextFormField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Salary',
prefixText: '\$',
suffixText: 'USD',
suffixStyle: const TextStyle(color: Colors.green)
new TextFormField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(
labelText: 'Salary',
prefixText: '\$',
suffixText: 'USD',
suffixStyle: const TextStyle(color: Colors.green)
),
maxLines: 1,
),
maxLines: 1,
),
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Expanded(
child: new TextFormField(
key: _passwordFieldKey,
decoration: const InputDecoration(
hintText: 'How do you log in?',
labelText: 'New Password *',
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Expanded(
child: new TextFormField(
key: _passwordFieldKey,
decoration: const InputDecoration(
hintText: 'How do you log in?',
labelText: 'New Password *',
),
obscureText: true,
onSaved: (String value) { person.password = value; },
),
obscureText: true,
onSaved: (String value) { person.password = value; },
),
),
const SizedBox(width: 16.0),
new Expanded(
child: new TextFormField(
decoration: const InputDecoration(
hintText: 'How do you log in?',
labelText: 'Re-type Password *',
const SizedBox(width: 16.0),
new Expanded(
child: new TextFormField(
decoration: const InputDecoration(
hintText: 'How do you log in?',
labelText: 'Re-type Password *',
),
obscureText: true,
validator: _validatePassword,
),
obscureText: true,
validator: _validatePassword,
),
],
),
new Container(
padding: const EdgeInsets.all(20.0),
alignment: Alignment.center,
child: new RaisedButton(
child: const Text('SUBMIT'),
onPressed: _handleSubmitted,
),
],
),
new Container(
padding: const EdgeInsets.all(20.0),
alignment: Alignment.center,
child: new RaisedButton(
child: const Text('SUBMIT'),
onPressed: _handleSubmitted,
),
),
new Container(
padding: const EdgeInsets.only(top: 20.0),
child: new Text('* indicates required field', style: Theme.of(context).textTheme.caption),
),
],
)
new Container(
padding: const EdgeInsets.only(top: 20.0),
child: new Text('* indicates required field', style: Theme.of(context).textTheme.caption),
),
],
),
),
),
);
}
......
......@@ -22,44 +22,48 @@ class TooltipDemo extends StatelessWidget {
),
body: new Builder(
builder: (BuildContext context) {
return new ListView(
children: <Widget>[
new Text(_introText, style: theme.textTheme.subhead),
new Row(
children: <Widget>[
new Text('Long press the ', style: theme.textTheme.subhead),
new Tooltip(
message: 'call icon',
child: new Icon(
Icons.call,
size: 18.0,
color: theme.iconTheme.color
)
),
new Text(' icon.', style: theme.textTheme.subhead)
]
),
new Center(
child: new IconButton(
iconSize: 48.0,
icon: const Icon(Icons.call),
color: theme.iconTheme.color,
tooltip: 'Place a phone call',
onPressed: () {
Scaffold.of(context).showSnackBar(const SnackBar(
content: const Text('That was an ordinary tap.')
));
}
return new SafeArea(
top: false,
bottom: false,
child: new ListView(
children: <Widget>[
new Text(_introText, style: theme.textTheme.subhead),
new Row(
children: <Widget>[
new Text('Long press the ', style: theme.textTheme.subhead),
new Tooltip(
message: 'call icon',
child: new Icon(
Icons.call,
size: 18.0,
color: theme.iconTheme.color
)
),
new Text(' icon.', style: theme.textTheme.subhead)
]
),
new Center(
child: new IconButton(
iconSize: 48.0,
icon: const Icon(Icons.call),
color: theme.iconTheme.color,
tooltip: 'Place a phone call',
onPressed: () {
Scaffold.of(context).showSnackBar(const SnackBar(
content: const Text('That was an ordinary tap.')
));
}
)
)
)
]
.map((Widget widget) {
return new Padding(
padding: const EdgeInsets.only(top: 16.0, left: 16.0, right: 16.0),
child: widget
);
})
.toList()
]
.map((Widget widget) {
return new Padding(
padding: const EdgeInsets.only(top: 16.0, left: 16.0, right: 16.0),
child: widget
);
})
.toList()
),
);
}
)
......
......@@ -77,16 +77,20 @@ class TabbedComponentDemoScaffold extends StatelessWidget {
),
body: new TabBarView(
children: demos.map((ComponentDemoTabData demo) {
return new Column(
children: <Widget>[
new Padding(
padding: const EdgeInsets.all(16.0),
child: new Text(demo.description,
style: Theme.of(context).textTheme.subhead
)
),
new Expanded(child: demo.demoWidget)
],
return new SafeArea(
top: false,
bottom: false,
child: new Column(
children: <Widget>[
new Padding(
padding: const EdgeInsets.all(16.0),
child: new Text(demo.description,
style: Theme.of(context).textTheme.subhead
)
),
new Expanded(child: demo.demoWidget)
],
),
);
}).toList(),
),
......
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