mirror of
https://github.com/flutter/samples.git
synced 2026-04-05 11:11:23 +00:00
Update gallery, fix Cupertino fonts by using GoogleSans instead (#155)
* Update gallery, fix Cupertino fonts Cupertino fonts fixed by using GoogleSans instead * remove BUILD.gn * remove ios and android dirs from web/gallery * remove meta/flutter_gallery.cmx * revert provider_shopper/pubspec.lock * remove gallery's test and tool directories * update web/gallery README
This commit is contained in:
@@ -302,8 +302,9 @@ class CalcExpression {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
final List<ExpressionToken> outList = <ExpressionToken>[];
|
||||
outList.add(ResultToken(currentTermValue));
|
||||
final List<ExpressionToken> outList = <ExpressionToken>[
|
||||
ResultToken(currentTermValue),
|
||||
];
|
||||
return CalcExpression(outList, ExpressionState.Result);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ class PaletteTabView extends StatelessWidget {
|
||||
);
|
||||
}),
|
||||
],
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,33 +54,31 @@ class _ContactItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
final List<Widget> columnChildren = lines.sublist(0, lines.length - 1).map<Widget>((String line) => Text(line)).toList();
|
||||
columnChildren.add(Text(lines.last, style: themeData.textTheme.caption));
|
||||
|
||||
final List<Widget> rowChildren = <Widget>[
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: columnChildren,
|
||||
),
|
||||
),
|
||||
];
|
||||
if (icon != null) {
|
||||
rowChildren.add(SizedBox(
|
||||
width: 72.0,
|
||||
child: IconButton(
|
||||
icon: Icon(icon),
|
||||
color: themeData.primaryColor,
|
||||
onPressed: onPressed,
|
||||
),
|
||||
));
|
||||
}
|
||||
return MergeSemantics(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: rowChildren,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
...lines.sublist(0, lines.length - 1).map<Widget>((String line) => Text(line)),
|
||||
Text(lines.last, style: themeData.textTheme.caption),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (icon != null)
|
||||
SizedBox(
|
||||
width: 72.0,
|
||||
child: IconButton(
|
||||
icon: Icon(icon),
|
||||
color: themeData.primaryColor,
|
||||
onPressed: onPressed,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -53,159 +53,146 @@ class _CupertinoAlertDemoState extends State<CupertinoAlertDemo> {
|
||||
style: CupertinoTheme.of(context).textTheme.textStyle,
|
||||
child: Builder(
|
||||
builder: (BuildContext context) {
|
||||
final List<Widget> stackChildren = <Widget>[
|
||||
CupertinoScrollbar(
|
||||
child: ListView(
|
||||
// Add more padding to the normal safe area.
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 72.0)
|
||||
+ MediaQuery.of(context).padding,
|
||||
children: <Widget>[
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert'),
|
||||
onPressed: () {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: CupertinoAlertDialog(
|
||||
title: const Text('Discard draft?'),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Discard'),
|
||||
isDestructiveAction: true,
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Discard');
|
||||
},
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Cancel'),
|
||||
isDefaultAction: true,
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Cancel');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert with Title'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: CupertinoAlertDialog(
|
||||
title: const Text('Allow "Maps" to access your location while you are using the app?'),
|
||||
content: const Text('Your current location will be displayed on the map and used '
|
||||
'for directions, nearby search results, and estimated travel times.'),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Don\'t Allow'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Disallow');
|
||||
},
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Allow'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Allow');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert with Buttons'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: const CupertinoDessertDialog(
|
||||
title: Text('Select Favorite Dessert'),
|
||||
content: Text('Please select your favorite type of dessert from the '
|
||||
'list below. Your selection will be used to customize the suggested '
|
||||
'list of eateries in your area.'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert Buttons Only'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: const CupertinoDessertDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Action Sheet'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () {
|
||||
showDemoActionSheet(
|
||||
context: context,
|
||||
child: CupertinoActionSheet(
|
||||
title: const Text('Favorite Dessert'),
|
||||
message: const Text('Please select the best dessert from the options below.'),
|
||||
actions: <Widget>[
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('Profiteroles'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Profiteroles');
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('Cannolis'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Cannolis');
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('Trifle'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Trifle');
|
||||
},
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
child: const Text('Cancel'),
|
||||
isDefaultAction: true,
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'Cancel');
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
if (lastSelectedValue != null) {
|
||||
stackChildren.add(
|
||||
Positioned(
|
||||
bottom: 32.0,
|
||||
child: Text('You selected: $lastSelectedValue'),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Stack(
|
||||
alignment: Alignment.center,
|
||||
children: stackChildren,
|
||||
children: <Widget>[
|
||||
CupertinoScrollbar(
|
||||
child: ListView(
|
||||
// Add more padding to the normal safe area.
|
||||
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 72.0)
|
||||
+ MediaQuery.of(context).padding,
|
||||
children: <Widget>[
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert'),
|
||||
onPressed: () => _onAlertPress(context),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert with Title'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () => _onAlertWithTitlePress(context),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert with Buttons'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () => _onAlertWithButtonsPress(context),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Alert Buttons Only'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: const CupertinoDessertDialog(),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
CupertinoButton.filled(
|
||||
child: const Text('Action Sheet'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 36.0),
|
||||
onPressed: () => _onActionSheetPress(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (lastSelectedValue != null)
|
||||
Positioned(
|
||||
bottom: 32.0,
|
||||
child: Text('You selected: $lastSelectedValue'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onAlertPress(BuildContext context) {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: CupertinoAlertDialog(
|
||||
title: const Text('Discard draft?'),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Discard'),
|
||||
isDestructiveAction: true,
|
||||
onPressed: () => Navigator.pop(context, 'Discard'),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Cancel'),
|
||||
isDefaultAction: true,
|
||||
onPressed: () => Navigator.pop(context, 'Cancel'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onAlertWithTitlePress(BuildContext context) {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: CupertinoAlertDialog(
|
||||
title: const Text('Allow "Maps" to access your location while you are using the app?'),
|
||||
content: const Text('Your current location will be displayed on the map and used '
|
||||
'for directions, nearby search results, and estimated travel times.'),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Don\'t Allow'),
|
||||
onPressed: () => Navigator.pop(context, 'Disallow'),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
child: const Text('Allow'),
|
||||
onPressed: () => Navigator.pop(context, 'Allow'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onAlertWithButtonsPress(BuildContext context) {
|
||||
showDemoDialog(
|
||||
context: context,
|
||||
child: const CupertinoDessertDialog(
|
||||
title: Text('Select Favorite Dessert'),
|
||||
content: Text('Please select your favorite type of dessert from the '
|
||||
'list below. Your selection will be used to customize the suggested '
|
||||
'list of eateries in your area.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onActionSheetPress(BuildContext context) {
|
||||
showDemoActionSheet(
|
||||
context: context,
|
||||
child: CupertinoActionSheet(
|
||||
title: const Text('Favorite Dessert'),
|
||||
message: const Text('Please select the best dessert from the options below.'),
|
||||
actions: <Widget>[
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('Profiteroles'),
|
||||
onPressed: () => Navigator.pop(context, 'Profiteroles'),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('Cannolis'),
|
||||
onPressed: () => Navigator.pop(context, 'Cannolis'),
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('Trifle'),
|
||||
onPressed: () => Navigator.pop(context, 'Trifle'),
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
child: const Text('Cancel'),
|
||||
isDefaultAction: true,
|
||||
onPressed: () => Navigator.pop(context, 'Cancel'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CupertinoDessertDialog extends StatelessWidget {
|
||||
|
||||
@@ -647,25 +647,21 @@ class Tab2ConversationRow extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> children = <Widget>[];
|
||||
if (avatar != null)
|
||||
children.add(avatar);
|
||||
|
||||
final bool isSelf = avatar == null;
|
||||
children.add(
|
||||
Tab2ConversationBubble(
|
||||
text: text,
|
||||
color: isSelf
|
||||
? Tab2ConversationBubbleColor.blue
|
||||
: Tab2ConversationBubbleColor.gray,
|
||||
),
|
||||
);
|
||||
return SafeArea(
|
||||
child: Row(
|
||||
mainAxisAlignment: isSelf ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: isSelf ? CrossAxisAlignment.center : CrossAxisAlignment.end,
|
||||
children: children,
|
||||
children: <Widget>[
|
||||
if (avatar != null) avatar,
|
||||
Tab2ConversationBubble(
|
||||
text: text,
|
||||
color: isSelf
|
||||
? Tab2ConversationBubbleColor.blue
|
||||
: Tab2ConversationBubbleColor.gray,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ class FruitPage extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
CircleAvatar(
|
||||
const CircleAvatar(
|
||||
backgroundImage: ExactAssetImage(
|
||||
'people/square/trevor.png',
|
||||
package: 'flutter_gallery_assets',
|
||||
|
||||
@@ -140,7 +140,7 @@ class CategoryView extends StatelessWidget {
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class _BannerDemoState extends State<BannerDemo> {
|
||||
setState(() {
|
||||
_displayBanner = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
if (_showMultipleActions)
|
||||
FlatButton(
|
||||
@@ -66,7 +66,7 @@ class _BannerDemoState extends State<BannerDemo> {
|
||||
setState(() {
|
||||
_displayBanner = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -164,10 +164,9 @@ class _BottomNavigationDemoState extends State<BottomNavigationDemo>
|
||||
}
|
||||
|
||||
Widget _buildTransitionsStack() {
|
||||
final List<FadeTransition> transitions = <FadeTransition>[];
|
||||
|
||||
for (NavigationIconView view in _navigationViews)
|
||||
transitions.add(view.transition(_type, context));
|
||||
final List<FadeTransition> transitions = <FadeTransition>[
|
||||
for (NavigationIconView view in _navigationViews) view.transition(_type, context),
|
||||
];
|
||||
|
||||
// We want to have the newly animating (fading in) views on top.
|
||||
transitions.sort((FadeTransition a, FadeTransition b) {
|
||||
|
||||
@@ -262,89 +262,83 @@ class TravelDestinationContent extends StatelessWidget {
|
||||
final TextStyle titleStyle = theme.textTheme.headline.copyWith(color: Colors.white);
|
||||
final TextStyle descriptionStyle = theme.textTheme.subhead;
|
||||
|
||||
final List<Widget> children = <Widget>[
|
||||
// Photo and title.
|
||||
SizedBox(
|
||||
height: 184.0,
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
// In order to have the ink splash appear above the image, you
|
||||
// must use Ink.image. This allows the image to be painted as part
|
||||
// of the Material and display ink effects above it. Using a
|
||||
// standard Image will obscure the ink splash.
|
||||
child: Ink.image(
|
||||
image: AssetImage(destination.assetName, package: destination.assetPackage),
|
||||
fit: BoxFit.cover,
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16.0,
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
destination.title,
|
||||
style: titleStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Description and share/explore buttons.
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
|
||||
child: DefaultTextStyle(
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: descriptionStyle,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
// Photo and title.
|
||||
SizedBox(
|
||||
height: 184.0,
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
// three line description
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
destination.description,
|
||||
style: descriptionStyle.copyWith(color: Colors.black54),
|
||||
Positioned.fill(
|
||||
// In order to have the ink splash appear above the image, you
|
||||
// must use Ink.image. This allows the image to be painted as part
|
||||
// of the Material and display ink effects above it. Using a
|
||||
// standard Image will obscure the ink splash.
|
||||
child: Ink.image(
|
||||
image: AssetImage(destination.assetName, package: destination.assetPackage),
|
||||
fit: BoxFit.cover,
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16.0,
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
destination.title,
|
||||
style: titleStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(destination.city),
|
||||
Text(destination.location),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
if (destination.type == CardDemoType.standard) {
|
||||
children.add(
|
||||
// share, explore buttons
|
||||
ButtonBar(
|
||||
alignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('SHARE', semanticsLabel: 'Share ${destination.title}'),
|
||||
textColor: Colors.amber.shade500,
|
||||
onPressed: () { print('pressed'); },
|
||||
// Description and share/explore buttons.
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0),
|
||||
child: DefaultTextStyle(
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: descriptionStyle,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
// three line description
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
destination.description,
|
||||
style: descriptionStyle.copyWith(color: Colors.black54),
|
||||
),
|
||||
),
|
||||
Text(destination.city),
|
||||
Text(destination.location),
|
||||
],
|
||||
),
|
||||
FlatButton(
|
||||
child: Text('EXPLORE', semanticsLabel: 'Explore ${destination.title}'),
|
||||
textColor: Colors.amber.shade500,
|
||||
onPressed: () { print('pressed'); },
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: children,
|
||||
if (destination.type == CardDemoType.standard)
|
||||
// share, explore buttons
|
||||
ButtonBar(
|
||||
alignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
FlatButton(
|
||||
child: Text('SHARE', semanticsLabel: 'Share ${destination.title}'),
|
||||
textColor: Colors.amber.shade500,
|
||||
onPressed: () { print('pressed'); },
|
||||
),
|
||||
FlatButton(
|
||||
child: Text('EXPLORE', semanticsLabel: 'Explore ${destination.title}'),
|
||||
textColor: Colors.amber.shade500,
|
||||
onPressed: () { print('pressed'); },
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,40 +83,36 @@ class _ChipsTile extends StatelessWidget {
|
||||
// Wraps a list of chips into a ListTile for display as a section in the demo.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> cardChildren = <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 16.0, bottom: 4.0),
|
||||
alignment: Alignment.center,
|
||||
child: Text(label, textAlign: TextAlign.start),
|
||||
),
|
||||
];
|
||||
if (children.isNotEmpty) {
|
||||
cardChildren.add(Wrap(
|
||||
children: children.map<Widget>((Widget chip) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
child: chip,
|
||||
);
|
||||
}).toList()));
|
||||
} else {
|
||||
final TextStyle textStyle = Theme.of(context).textTheme.caption.copyWith(fontStyle: FontStyle.italic);
|
||||
cardChildren.add(
|
||||
Semantics(
|
||||
container: true,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0),
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text('None', style: textStyle),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return Card(
|
||||
semanticContainer: false,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: cardChildren,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 16.0, bottom: 4.0),
|
||||
alignment: Alignment.center,
|
||||
child: Text(label, textAlign: TextAlign.start),
|
||||
),
|
||||
if (children.isNotEmpty)
|
||||
Wrap(
|
||||
children: children.map<Widget>((Widget chip) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(2.0),
|
||||
child: chip,
|
||||
);
|
||||
}).toList(),
|
||||
)
|
||||
else
|
||||
Semantics(
|
||||
container: true,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
constraints: const BoxConstraints(minWidth: 48.0, minHeight: 48.0),
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text('None', style: Theme.of(context).textTheme.caption.copyWith(fontStyle: FontStyle.italic)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -245,14 +245,18 @@ class _LeaveBehindListItem extends StatelessWidget {
|
||||
},
|
||||
background: Container(
|
||||
color: theme.primaryColor,
|
||||
child: const ListTile(
|
||||
leading: Icon(Icons.delete, color: Colors.white, size: 36.0),
|
||||
child: const Center(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.delete, color: Colors.white, size: 36.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
secondaryBackground: Container(
|
||||
color: theme.primaryColor,
|
||||
child: const ListTile(
|
||||
trailing: Icon(Icons.archive, color: Colors.white, size: 36.0),
|
||||
child: const Center(
|
||||
child: ListTile(
|
||||
trailing: Icon(Icons.archive, color: Colors.white, size: 36.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
|
||||
@@ -204,22 +204,23 @@ class _SearchDemoSearchDelegate extends SearchDelegate<int> {
|
||||
@override
|
||||
List<Widget> buildActions(BuildContext context) {
|
||||
return <Widget>[
|
||||
query.isEmpty
|
||||
? IconButton(
|
||||
tooltip: 'Voice Search',
|
||||
icon: const Icon(Icons.mic),
|
||||
onPressed: () {
|
||||
query = 'TODO: implement voice input';
|
||||
},
|
||||
)
|
||||
: IconButton(
|
||||
tooltip: 'Clear',
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
query = '';
|
||||
showSuggestions(context);
|
||||
},
|
||||
),
|
||||
if (query.isEmpty)
|
||||
IconButton(
|
||||
tooltip: 'Voice Search',
|
||||
icon: const Icon(Icons.mic),
|
||||
onPressed: () {
|
||||
query = 'TODO: implement voice input';
|
||||
},
|
||||
)
|
||||
else
|
||||
IconButton(
|
||||
tooltip: 'Clear',
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
query = '';
|
||||
showSuggestions(context);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class _SnackBarDemoState extends State<SnackBarDemo> {
|
||||
tooltip: 'Create',
|
||||
onPressed: () {
|
||||
print('Floating Action Button was pressed');
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,65 @@ const Cubic _kDecelerateCurve = Cubic(0.23, 0.94, 0.41, 1.0);
|
||||
const double _kPeakVelocityTime = 0.248210;
|
||||
const double _kPeakVelocityProgress = 0.379146;
|
||||
|
||||
class _TappableWhileStatusIs extends StatefulWidget {
|
||||
const _TappableWhileStatusIs(
|
||||
this.status, {
|
||||
Key key,
|
||||
this.controller,
|
||||
this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
final AnimationController controller;
|
||||
final AnimationStatus status;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
_TappableWhileStatusIsState createState() => _TappableWhileStatusIsState();
|
||||
}
|
||||
|
||||
class _TappableWhileStatusIsState extends State<_TappableWhileStatusIs> {
|
||||
bool _active;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.controller.addStatusListener(_handleStatusChange);
|
||||
_active = widget.controller.status == widget.status;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.controller.removeStatusListener(_handleStatusChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _handleStatusChange(AnimationStatus status) {
|
||||
final bool value = widget.controller.status == widget.status;
|
||||
if (_active != value) {
|
||||
setState(() {
|
||||
_active = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget child = AbsorbPointer(
|
||||
absorbing: !_active,
|
||||
child: widget.child,
|
||||
);
|
||||
|
||||
if (!_active) {
|
||||
child = FocusScope(
|
||||
canRequestFocus: false,
|
||||
debugLabel: '$_TappableWhileStatusIs',
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
class _FrontLayer extends StatelessWidget {
|
||||
const _FrontLayer({
|
||||
Key key,
|
||||
@@ -275,12 +334,20 @@ class _BackdropState extends State<Backdrop> with SingleTickerProviderStateMixin
|
||||
return Stack(
|
||||
key: _backdropKey,
|
||||
children: <Widget>[
|
||||
widget.backLayer,
|
||||
_TappableWhileStatusIs(
|
||||
AnimationStatus.dismissed,
|
||||
controller: _controller,
|
||||
child: widget.backLayer,
|
||||
),
|
||||
PositionedTransition(
|
||||
rect: _layerAnimation,
|
||||
child: _FrontLayer(
|
||||
onTap: _toggleBackdropLayerVisibility,
|
||||
child: widget.frontLayer,
|
||||
child: _TappableWhileStatusIs(
|
||||
AnimationStatus.completed,
|
||||
controller: _controller,
|
||||
child: widget.frontLayer,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -48,6 +48,8 @@ class TypographyDemo extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final TextTheme textTheme = Theme.of(context).textTheme;
|
||||
final List<Widget> styleItems = <Widget>[
|
||||
if (MediaQuery.of(context).size.width > 500.0)
|
||||
TextStyleItem(name: 'Display 4', style: textTheme.display4, text: 'Light 112sp'),
|
||||
TextStyleItem(name: 'Display 3', style: textTheme.display3, text: 'Regular 56sp'),
|
||||
TextStyleItem(name: 'Display 2', style: textTheme.display2, text: 'Regular 45sp'),
|
||||
TextStyleItem(name: 'Display 1', style: textTheme.display1, text: 'Regular 34sp'),
|
||||
@@ -60,14 +62,6 @@ class TypographyDemo extends StatelessWidget {
|
||||
TextStyleItem(name: 'Button', style: textTheme.button, text: 'MEDIUM (ALL CAPS) 14sp'),
|
||||
];
|
||||
|
||||
if (MediaQuery.of(context).size.width > 500.0) {
|
||||
styleItems.insert(0, TextStyleItem(
|
||||
name: 'Display 4',
|
||||
style: textTheme.display4,
|
||||
text: 'Light 112sp',
|
||||
));
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Typography')),
|
||||
body: SafeArea(
|
||||
|
||||
@@ -66,10 +66,19 @@ class _TappableWhileStatusIsState extends State<_TappableWhileStatusIs> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AbsorbPointer(
|
||||
Widget child = AbsorbPointer(
|
||||
absorbing: !_active,
|
||||
child: widget.child,
|
||||
);
|
||||
|
||||
if (!_active) {
|
||||
child = FocusScope(
|
||||
canRequestFocus: false,
|
||||
debugLabel: '$_TappableWhileStatusIs',
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,36 +147,31 @@ class _BackAppBar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> children = <Widget>[
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 56.0,
|
||||
child: leading,
|
||||
),
|
||||
Expanded(
|
||||
child: title,
|
||||
),
|
||||
];
|
||||
|
||||
if (trailing != null) {
|
||||
children.add(
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 56.0,
|
||||
child: trailing,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final ThemeData theme = Theme.of(context);
|
||||
|
||||
return IconTheme.merge(
|
||||
data: theme.primaryIconTheme,
|
||||
child: DefaultTextStyle(
|
||||
style: theme.primaryTextTheme.title,
|
||||
child: SizedBox(
|
||||
height: _kBackAppBarHeight,
|
||||
child: Row(children: children),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 56.0,
|
||||
child: leading,
|
||||
),
|
||||
Expanded(
|
||||
child: title,
|
||||
),
|
||||
if (trailing != null)
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 56.0,
|
||||
child: trailing,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -255,95 +259,92 @@ class _BackdropState extends State<Backdrop> with SingleTickerProviderStateMixin
|
||||
begin: RelativeRect.fromLTRB(0.0, constraints.biggest.height - _kFrontClosedHeight, 0.0, 0.0),
|
||||
end: const RelativeRect.fromLTRB(0.0, _kBackAppBarHeight, 0.0, 0.0),
|
||||
));
|
||||
|
||||
final List<Widget> layers = <Widget>[
|
||||
// Back layer
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
_BackAppBar(
|
||||
leading: widget.frontAction,
|
||||
title: _CrossFadeTransition(
|
||||
progress: _controller,
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child0: Semantics(namesRoute: true, child: widget.frontTitle),
|
||||
child1: Semantics(namesRoute: true, child: widget.backTitle),
|
||||
),
|
||||
trailing: IconButton(
|
||||
onPressed: _toggleFrontLayer,
|
||||
tooltip: 'Toggle options page',
|
||||
icon: AnimatedIcon(
|
||||
icon: AnimatedIcons.close_menu,
|
||||
progress: _controller,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Visibility(
|
||||
child: widget.backLayer,
|
||||
visible: _controller.status != AnimationStatus.completed,
|
||||
maintainState: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Front layer
|
||||
PositionedTransition(
|
||||
rect: frontRelativeRect,
|
||||
child: AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (BuildContext context, Widget child) {
|
||||
return PhysicalShape(
|
||||
elevation: 12.0,
|
||||
color: Theme.of(context).canvasColor,
|
||||
clipper: ShapeBorderClipper(
|
||||
shape: BeveledRectangleBorder(
|
||||
borderRadius: _kFrontHeadingBevelRadius.transform(_controller.value),
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: _TappableWhileStatusIs(
|
||||
AnimationStatus.completed,
|
||||
controller: _controller,
|
||||
child: FadeTransition(
|
||||
opacity: _frontOpacity,
|
||||
child: widget.frontLayer,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
// The front "heading" is a (typically transparent) widget that's stacked on
|
||||
// top of, and at the top of, the front layer. It adds support for dragging
|
||||
// the front layer up and down and for opening and closing the front layer
|
||||
// with a tap. It may obscure part of the front layer's topmost child.
|
||||
if (widget.frontHeading != null) {
|
||||
layers.add(
|
||||
PositionedTransition(
|
||||
rect: frontRelativeRect,
|
||||
child: ExcludeSemantics(
|
||||
child: Container(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: _toggleFrontLayer,
|
||||
onVerticalDragUpdate: _handleDragUpdate,
|
||||
onVerticalDragEnd: _handleDragEnd,
|
||||
child: widget.frontHeading,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Stack(
|
||||
key: _backdropKey,
|
||||
children: layers,
|
||||
children: <Widget>[
|
||||
// Back layer
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
_BackAppBar(
|
||||
leading: widget.frontAction,
|
||||
title: _CrossFadeTransition(
|
||||
progress: _controller,
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child0: Semantics(namesRoute: true, child: widget.frontTitle),
|
||||
child1: Semantics(namesRoute: true, child: widget.backTitle),
|
||||
),
|
||||
trailing: IconButton(
|
||||
onPressed: _toggleFrontLayer,
|
||||
tooltip: 'Toggle options page',
|
||||
icon: AnimatedIcon(
|
||||
icon: AnimatedIcons.close_menu,
|
||||
progress: _controller,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _TappableWhileStatusIs(
|
||||
AnimationStatus.dismissed,
|
||||
controller: _controller,
|
||||
child: Visibility(
|
||||
child: widget.backLayer,
|
||||
visible: _controller.status != AnimationStatus.completed,
|
||||
maintainState: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Front layer
|
||||
PositionedTransition(
|
||||
rect: frontRelativeRect,
|
||||
child: AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (BuildContext context, Widget child) {
|
||||
return PhysicalShape(
|
||||
elevation: 12.0,
|
||||
color: Theme.of(context).canvasColor,
|
||||
clipper: ShapeBorderClipper(
|
||||
shape: BeveledRectangleBorder(
|
||||
borderRadius: _kFrontHeadingBevelRadius.transform(_controller.value),
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: _TappableWhileStatusIs(
|
||||
AnimationStatus.completed,
|
||||
controller: _controller,
|
||||
child: FadeTransition(
|
||||
opacity: _frontOpacity,
|
||||
child: widget.frontLayer,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// The front "heading" is a (typically transparent) widget that's stacked on
|
||||
// top of, and at the top of, the front layer. It adds support for dragging
|
||||
// the front layer up and down and for opening and closing the front layer
|
||||
// with a tap. It may obscure part of the front layer's topmost child.
|
||||
if (widget.frontHeading != null)
|
||||
PositionedTransition(
|
||||
rect: frontRelativeRect,
|
||||
child: ExcludeSemantics(
|
||||
child: Container(
|
||||
alignment: Alignment.topLeft,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: _toggleFrontLayer,
|
||||
onVerticalDragUpdate: _handleDragUpdate,
|
||||
onVerticalDragEnd: _handleDragEnd,
|
||||
child: widget.frontHeading,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -184,26 +184,6 @@ class _DemoItem extends StatelessWidget {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final bool isDark = theme.brightness == Brightness.dark;
|
||||
final double textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||
|
||||
final List<Widget> titleChildren = <Widget>[
|
||||
Text(
|
||||
demo.title,
|
||||
style: theme.textTheme.subhead.copyWith(
|
||||
color: isDark ? Colors.white : const Color(0xFF202124),
|
||||
),
|
||||
),
|
||||
];
|
||||
if (demo.subtitle != null) {
|
||||
titleChildren.add(
|
||||
Text(
|
||||
demo.subtitle,
|
||||
style: theme.textTheme.body1.copyWith(
|
||||
color: isDark ? Colors.white : const Color(0xFF60646B)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return RawMaterialButton(
|
||||
padding: EdgeInsets.zero,
|
||||
splashColor: theme.primaryColor.withOpacity(0.12),
|
||||
@@ -229,7 +209,21 @@ class _DemoItem extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: titleChildren,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
demo.title,
|
||||
style: theme.textTheme.subhead.copyWith(
|
||||
color: isDark ? Colors.white : const Color(0xFF202124),
|
||||
),
|
||||
),
|
||||
if (demo.subtitle != null)
|
||||
Text(
|
||||
demo.subtitle,
|
||||
style: theme.textTheme.body1.copyWith(
|
||||
color: isDark ? Colors.white : const Color(0xFF60646B)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 44.0),
|
||||
@@ -294,11 +288,11 @@ class _GalleryHomeState extends State<GalleryHome> with SingleTickerProviderStat
|
||||
GalleryDemoCategory _category;
|
||||
|
||||
static Widget _topHomeLayout(Widget currentChild, List<Widget> previousChildren) {
|
||||
List<Widget> children = previousChildren;
|
||||
if (currentChild != null)
|
||||
children = children.toList()..add(currentChild);
|
||||
return Stack(
|
||||
children: children,
|
||||
children: <Widget>[
|
||||
...previousChildren,
|
||||
if (currentChild != null) currentChild,
|
||||
],
|
||||
alignment: Alignment.topCenter,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -425,13 +425,10 @@ class GalleryOptionsPage extends StatelessWidget {
|
||||
options.showPerformanceOverlay == null)
|
||||
return const <Widget>[];
|
||||
|
||||
final List<Widget> items = <Widget>[
|
||||
return <Widget>[
|
||||
const Divider(),
|
||||
const _Heading('Diagnostics'),
|
||||
];
|
||||
|
||||
if (options.showOffscreenLayersCheckerboard != null) {
|
||||
items.add(
|
||||
if (options.showOffscreenLayersCheckerboard != null)
|
||||
_BooleanItem(
|
||||
'Highlight offscreen layers',
|
||||
options.showOffscreenLayersCheckerboard,
|
||||
@@ -439,10 +436,7 @@ class GalleryOptionsPage extends StatelessWidget {
|
||||
onOptionsChanged(options.copyWith(showOffscreenLayersCheckerboard: value));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
if (options.showRasterCacheImagesCheckerboard != null) {
|
||||
items.add(
|
||||
if (options.showRasterCacheImagesCheckerboard != null)
|
||||
_BooleanItem(
|
||||
'Highlight raster cache images',
|
||||
options.showRasterCacheImagesCheckerboard,
|
||||
@@ -450,10 +444,7 @@ class GalleryOptionsPage extends StatelessWidget {
|
||||
onOptionsChanged(options.copyWith(showRasterCacheImagesCheckerboard: value));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
if (options.showPerformanceOverlay != null) {
|
||||
items.add(
|
||||
if (options.showPerformanceOverlay != null)
|
||||
_BooleanItem(
|
||||
'Show performance overlay',
|
||||
options.showPerformanceOverlay,
|
||||
@@ -461,10 +452,7 @@ class GalleryOptionsPage extends StatelessWidget {
|
||||
onOptionsChanged(options.copyWith(showPerformanceOverlay: value));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return items;
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user