more UI-as-code (#35516)

This commit is contained in:
Alexandre Ardhuin 2019-09-17 16:23:44 +02:00 committed by GitHub
parent d03aecab58
commit df4bf453ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
117 changed files with 1728 additions and 2132 deletions

View File

@ -140,7 +140,7 @@ linter:
- prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested
- prefer_generic_function_type_aliases
# - prefer_if_elements_to_conditional_expressions # not yet tested
- prefer_if_elements_to_conditional_expressions
- prefer_if_null_operators
- prefer_initializing_formals
- prefer_inlined_adds

View File

@ -208,23 +208,20 @@ class SampleChecker {
/// Computes the headers needed for each sample file.
List<Line> get headers {
if (_headers == null) {
final List<String> buffer = <String>[];
buffer.add('// generated code');
buffer.add('import \'dart:async\';');
buffer.add('import \'dart:convert\';');
buffer.add('import \'dart:math\' as math;');
buffer.add('import \'dart:typed_data\';');
buffer.add('import \'dart:ui\' as ui;');
buffer.add('import \'package:flutter_test/flutter_test.dart\';');
for (File file in _listDartFiles(Directory(_defaultFlutterPackage))) {
buffer.add('');
buffer.add('// ${file.path}');
buffer.add('import \'package:flutter/${path.basename(file.path)}\';');
}
_headers = buffer.map<Line>((String code) => Line(code)).toList();
}
return _headers;
return _headers ??= <String>[
'// generated code',
"import 'dart:async';",
"import 'dart:convert';",
"import 'dart:math' as math;",
"import 'dart:typed_data';",
"import 'dart:ui' as ui;",
"import 'package:flutter_test/flutter_test.dart';",
for (File file in _listDartFiles(Directory(_defaultFlutterPackage))) ...<String>[
'',
'// ${file.path}',
"import 'package:flutter/${path.basename(file.path)}';",
],
].map<Line>((String code) => Line(code)).toList();
}
List<Line> _headers;

View File

@ -177,7 +177,7 @@ Future<void> _checkForTrailingSpaces() async {
'*.dart', '*.cxx', '*.cpp', '*.cc', '*.c', '*.C', '*.h', '*.java', '*.mm', '*.m', '*.yml',
];
final EvalResult changedFilesResult = await _evalCommand(
'git', <String>['diff', '-U0', '--no-color', '--name-only', commitRange, '--'] + fileTypes,
'git', <String>['diff', '-U0', '--no-color', '--name-only', commitRange, '--', ...fileTypes],
workingDirectory: flutterRoot,
);
if (changedFilesResult.stdout == null || changedFilesResult.stdout.trim().isEmpty) {
@ -195,7 +195,8 @@ Future<void> _checkForTrailingSpaces() async {
'--line-number',
'--extended-regexp',
r'[[:blank:]]$',
] + changedFiles,
...changedFiles,
],
workingDirectory: flutterRoot,
failureMessage: '${red}Whitespace detected at the end of source code lines.$reset\nPlease remove:',
expectNonZeroExit: true, // Just means a non-zero exit code is expected.

View File

@ -527,20 +527,16 @@ class ArchivePublisher {
// Search for any entries with the same hash and channel and remove them.
final List<dynamic> releases = jsonData['releases'];
final List<Map<String, dynamic>> prunedReleases = <Map<String, dynamic>>[];
for (Map<String, dynamic> entry in releases) {
if (entry['hash'] != newEntry['hash'] || entry['channel'] != newEntry['channel']) {
prunedReleases.add(entry);
}
}
prunedReleases.add(newEntry);
prunedReleases.sort((Map<String, dynamic> a, Map<String, dynamic> b) {
jsonData['releases'] = <Map<String, dynamic>>[
for (Map<String, dynamic> entry in releases)
if (entry['hash'] != newEntry['hash'] || entry['channel'] != newEntry['channel'])
entry,
newEntry,
]..sort((Map<String, dynamic> a, Map<String, dynamic> b) {
final DateTime aDate = DateTime.parse(a['release_date']);
final DateTime bDate = DateTime.parse(b['release_date']);
return bDate.compareTo(aDate);
});
jsonData['releases'] = prunedReleases;
return jsonData;
}

View File

@ -184,17 +184,16 @@ Future<bq.BigqueryApi> _getBigqueryApi() async {
// Partition tool tests into two groups, see explanation on `_runToolCoverage`.
List<List<String>> _partitionToolTests() {
final List<String> pending = <String>[];
final String toolTestDir = path.join(toolRoot, 'test');
for (FileSystemEntity entity in Directory(toolTestDir).listSync(recursive: true)) {
if (entity is File && entity.path.endsWith('_test.dart')) {
final String relativePath = path.relative(entity.path, from: toolRoot);
pending.add(relativePath);
}
}
final List<String> pending = <String>[
for (FileSystemEntity entity in Directory(toolTestDir).listSync(recursive: true))
if (entity is File && entity.path.endsWith('_test.dart'))
path.relative(entity.path, from: toolRoot),
];
// Shuffle the tests to avoid giving an expensive test directory like
// integration to a single run of tests.
pending..shuffle();
pending.shuffle();
final int aboutHalf = pending.length ~/ 2;
final List<String> groupA = pending.take(aboutHalf).toList();
final List<String> groupB = pending.skip(aboutHalf).toList();
@ -512,19 +511,20 @@ Future<void> _buildRunnerTest(
bool enableFlutterToolAsserts = false,
bq.TabledataResourceApi tableData,
}) async {
final List<String> args = <String>['run', 'build_runner', 'test', '--', useFlutterTestFormatter ? '-rjson' : '-rcompact', '-j1'];
if (!hasColor) {
args.add('--no-color');
}
if (testPath != null) {
args.add(testPath);
}
final List<String> args = <String>[
'run',
'build_runner',
'test',
'--',
if (useFlutterTestFormatter) '-rjson' else '-rcompact',
'-j1',
if (!hasColor) '--no-color',
if (testPath != null) testPath,
];
final Map<String, String> pubEnvironment = <String, String>{
'FLUTTER_ROOT': flutterRoot,
if (Directory(pubCache).existsSync()) 'PUB_CACHE': pubCache,
};
if (Directory(pubCache).existsSync()) {
pubEnvironment['PUB_CACHE'] = pubCache;
}
if (enableFlutterToolAsserts) {
// If an existing env variable exists append to it, but only if
// it doesn't appear to already include enable-asserts.
@ -574,15 +574,17 @@ Future<void> _pubRunTest(
bool enableFlutterToolAsserts = false,
bq.TabledataResourceApi tableData,
}) async {
final List<String> args = <String>['run', 'test', useFlutterTestFormatter ? '-rjson' : '-rcompact', '-j1'];
if (!hasColor)
args.add('--no-color');
if (testPath != null)
args.add(testPath);
final Map<String, String> pubEnvironment = <String, String>{};
if (Directory(pubCache).existsSync()) {
pubEnvironment['PUB_CACHE'] = pubCache;
}
final List<String> args = <String>[
'run',
'test',
if (useFlutterTestFormatter) '-rjson' else '-rcompact',
'-j1',
if (!hasColor) '--no-color',
if (testPath != null) testPath,
];
final Map<String, String> pubEnvironment = <String, String>{
if (Directory(pubCache).existsSync()) 'PUB_CACHE': pubCache,
};
if (enableFlutterToolAsserts) {
// If an existing env variable exists append to it, but only if
// it doesn't appear to already include enable-asserts.

View File

@ -71,7 +71,7 @@ Future<Process> _run({@required Device device, @required List<String> command, @
await inDirectory(appDir, () async {
runner = await startProcess(
path.join(flutterDirectory.path, 'bin', 'flutter'),
<String>['--suppress-analytics', '-d', device.deviceId] + command,
<String>['--suppress-analytics', '-d', device.deviceId, ...command],
isBot: false, // we just want to test the output, not have any debugging info
);
final StreamController<String> stdout = StreamController<String>.broadcast();

View File

@ -82,12 +82,11 @@ Future<Map<String, dynamic>> runTask(
}
Future<VMIsolateRef> _connectToRunnerIsolate(Uri vmServiceUri) async {
final List<String> pathSegments = <String>[];
if (vmServiceUri.pathSegments.isNotEmpty) {
final List<String> pathSegments = <String>[
// Add authentication code.
pathSegments.add(vmServiceUri.pathSegments[0]);
}
pathSegments.add('ws');
if (vmServiceUri.pathSegments.isNotEmpty) vmServiceUri.pathSegments[0],
'ws',
];
final String url = vmServiceUri.replace(scheme: 'ws', pathSegments:
pathSegments).toString();
final Stopwatch stopwatch = Stopwatch()..start();

View File

@ -65,12 +65,10 @@ abstract class _Benchmark {
Directory get directory;
List<String> get options {
final List<String> result = <String>[ '--benchmark' ];
if (watch)
result.add('--watch');
return result;
}
List<String> get options => <String>[
'--benchmark',
if (watch) '--watch',
];
Future<double> execute(int iteration, int targetIterations) async {
section('Analyze $title ${watch ? 'with watcher' : ''} - ${iteration + 1} / $targetIterations');

View File

@ -119,13 +119,11 @@ Future<void> saveCatalogScreenshots({
String token, // Cloud storage authorization token.
String prefix, // Prefix for all file names.
}) async {
final List<String> screenshots = <String>[];
for (FileSystemEntity entity in directory.listSync()) {
if (entity is File && entity.path.endsWith('.png')) {
final File file = entity;
screenshots.add(file.path);
}
}
final List<String> screenshots = <String>[
for (FileSystemEntity entity in directory.listSync())
if (entity is File && entity.path.endsWith('.png'))
entity.path,
];
final List<String> largeNames = <String>[]; // Cloud storage names for the full res screenshots.
final List<String> smallNames = <String>[]; // Likewise for the scaled down screenshots.

View File

@ -144,13 +144,9 @@ class AndroidSemanticsNode {
}
/// Gets a list of [AndroidSemanticsActions] which are defined for the node.
List<AndroidSemanticsAction> getActions() {
final List<AndroidSemanticsAction> result = <AndroidSemanticsAction>[];
for (int id in _values['actions']) {
result.add(AndroidSemanticsAction.deserialize(id));
}
return result;
}
List<AndroidSemanticsAction> getActions() => <AndroidSemanticsAction>[
for (int id in _values['actions']) AndroidSemanticsAction.deserialize(id),
];
@override
String toString() {

View File

@ -34,7 +34,7 @@ class _ExampleWidgetState extends State<ExampleWidget> {
});
},
),
_pressed ? GeneratedWidget() : const SizedBox(),
if (_pressed) GeneratedWidget() else const SizedBox(),
],
),
),

View File

@ -3,7 +3,7 @@ description: A test of Flutter integrating code generation.
environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.2.2 <3.0.0"
dependencies:
flutter:

View File

@ -179,26 +179,27 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
@override
Widget build(BuildContext context) {
final List<Widget> layers = <Widget>[
Scaffold(
appBar: AppBar(title: const Text('Tap a Card')),
body: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
child: NotificationListener<ScrollNotification>(
onNotification: handleScrollNotification,
child: ListView.custom(
childrenDelegate: CardBuilder(
cardModels: cardModels,
onTapUp: handleTapUp,
return Stack(
children: <Widget>[
Scaffold(
appBar: AppBar(title: const Text('Tap a Card')),
body: Container(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 8.0),
child: NotificationListener<ScrollNotification>(
onNotification: handleScrollNotification,
child: ListView.custom(
childrenDelegate: CardBuilder(
cardModels: cardModels,
onTapUp: handleTapUp,
),
),
),
),
),
),
];
for (MarkerType type in markers.keys)
layers.add(Marker(type: type, position: markers[type]));
return Stack(children: layers);
for (MarkerType type in markers.keys)
Marker(type: type, position: markers[type]),
],
);
}
}

View File

@ -556,9 +556,6 @@ class _UnderlinesState extends State<Underlines> {
@override
Widget build(BuildContext context) {
final List<Widget> lines = <Widget>[_wrap(null)];
for (TextDecorationStyle style in TextDecorationStyle.values)
lines.add(_wrap(style));
final Size size = MediaQuery.of(context).size;
return Container(
color: Colors.black,
@ -572,7 +569,10 @@ class _UnderlinesState extends State<Underlines> {
vertical: size.height * 0.1,
),
child: ListBody(
children: lines,
children: <Widget>[
_wrap(null),
for (TextDecorationStyle style in TextDecorationStyle.values) _wrap(style),
],
),
),
),
@ -647,9 +647,6 @@ class _FallbackState extends State<Fallback> {
@override
Widget build(BuildContext context) {
final List<Widget> lines = <Widget>[];
for (String font in androidFonts)
lines.add(Text(multiScript, style: style.copyWith(fontFamily: font, fontSize: math.exp(_fontSize))));
final Size size = MediaQuery.of(context).size;
return Container(
color: Colors.black,
@ -666,7 +663,16 @@ class _FallbackState extends State<Fallback> {
),
child: IntrinsicWidth(
child: ListBody(
children: lines,
children: <Widget>[
for (String font in androidFonts)
Text(
multiScript,
style: style.copyWith(
fontFamily: font,
fontSize: math.exp(_fontSize),
),
),
],
),
),
),

View File

@ -2,7 +2,7 @@ name: manual_tests
environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.2.0 <3.0.0"
sdk: ">=2.2.2 <3.0.0"
dependencies:
flutter:

View File

@ -108,11 +108,12 @@ Future<void> main(List<String> arguments) async {
createSearchMetadata('$kDocsRoot/lib/opensearch.xml', '$kDocsRoot/doc/opensearch.xml');
cleanOutSnippets();
final List<String> dartdocBaseArgs = <String>['global', 'run'];
if (args['checked']) {
dartdocBaseArgs.add('-c');
}
dartdocBaseArgs.add('dartdoc');
final List<String> dartdocBaseArgs = <String>[
'global',
'run',
if (args['checked']) '-c',
'dartdoc',
];
// Verify which version of dartdoc we're using.
final ProcessResult result = Process.runSync(
@ -123,24 +124,17 @@ Future<void> main(List<String> arguments) async {
);
print('\n${result.stdout}flutter version: $version\n');
dartdocBaseArgs.add('--allow-tools');
if (args['json']) {
dartdocBaseArgs.add('--json');
}
if (args['validate-links']) {
dartdocBaseArgs.add('--validate-links');
} else {
dartdocBaseArgs.add('--no-validate-links');
}
dartdocBaseArgs.addAll(<String>['--link-to-source-excludes', '../../bin/cache',
'--link-to-source-root', '../..',
'--link-to-source-uri-template', 'https://github.com/flutter/flutter/blob/master/%f%#L%l%']);
// Generate the documentation.
// We don't need to exclude flutter_tools in this list because it's not in the
// recursive dependencies of the package defined at dev/docs/pubspec.yaml
final List<String> dartdocArgs = <String>[
...dartdocBaseArgs,
'--allow-tools',
if (args['json']) '--json',
if (args['validate-links']) '--validate-links' else '--no-validate-links',
'--link-to-source-excludes', '../../bin/cache',
'--link-to-source-root', '../..',
'--link-to-source-uri-template', 'https://github.com/flutter/flutter/blob/master/%f%#L%l%',
'--inject-html',
'--header', 'styles.html',
'--header', 'analytics.html',

View File

@ -52,10 +52,9 @@ class KeyData {
/// Parses the given JSON data and populates the data structure from it.
KeyData.fromJson(Map<String, dynamic> contentMap) {
data = <Key>[];
for (String key in contentMap.keys) {
data.add(Key.fromJsonMapEntry(key, contentMap[key]));
}
data = <Key>[
for (String key in contentMap.keys) Key.fromJsonMapEntry(key, contentMap[key]),
];
}
/// Converts the data structure into a JSON structure that can be parsed by

View File

@ -3,7 +3,7 @@ description: Generates keycode source files from various resources.
environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.2.2 <3.0.0"
dependencies:
args: 1.5.2

View File

@ -64,11 +64,9 @@ void main(List<String> args) {
return;
}
final List<FrameData> frames = <FrameData>[];
for (String filePath in argResults.rest) {
final FrameData data = interpretSvg(filePath);
frames.add(data);
}
final List<FrameData> frames = <FrameData>[
for (String filePath in argResults.rest) interpretSvg(filePath),
];
final StringBuffer generatedSb = StringBuffer();

View File

@ -6,7 +6,7 @@ author: Flutter Authors <flutter-dev@googlegroups.com>
environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.2.2 <3.0.0"
dependencies:
args: 1.5.2

View File

@ -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);
}

View File

@ -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,
),
),
],
),
),
);

View File

@ -53,153 +53,148 @@ 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(
return Stack(
alignment: Alignment.center,
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: () {
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');
},
),
],
),
);
},
),
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,
if (lastSelectedValue != null)
Positioned(
bottom: 32.0,
child: Text('You selected: $lastSelectedValue'),
),
],
);
},
),

View File

@ -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,
),
],
),
);
}

View File

@ -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) {

View File

@ -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'); },
),
],
),
],
);
}
}

View File

@ -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)),
),
),
],
),
);
}

View File

@ -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);
},
),
];
}
}

View File

@ -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(

View File

@ -138,36 +138,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 +250,88 @@ 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: 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,
),
),
),
),
],
);
}

View File

@ -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,
);
}

View File

@ -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

View File

@ -85,12 +85,7 @@ class AdaptiveContainer extends StatelessWidget {
}
}
List<String> _initNames() {
final List<String> names = <String>[];
for (int i = 0; i < 30; i++)
names.add('Item $i');
return names;
}
List<String> _initNames() => List<String>.generate(30, (int i) => 'Item $i');
final List<String> _kNames = _initNames();

View File

@ -94,25 +94,20 @@ class _StyledTextDemoState extends State<StyledTextDemo> {
@override
Widget build(BuildContext context) {
final List<Widget> lines = _kNameLines
.map<Widget>((List<String> nameAndText) => _toText(nameAndText[0], nameAndText[1]))
.toList();
final List<Widget> children = <Widget>[];
for (Widget line in lines) {
children.add(line);
if (line != lines.last)
children.add(SpeakerSeparator());
}
return GestureDetector(
onTap: _handleTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
children: children,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: _kNameLines
.map<Widget>((List<String> nameAndText) => _toText(nameAndText[0], nameAndText[1]))
.expand((Widget line) => <Widget>[
line,
SpeakerSeparator(),
])
.toList()..removeLast(),
),
),
);

View File

@ -174,16 +174,17 @@ class CupertinoAlertDialog extends StatelessWidget {
final ScrollController actionScrollController;
Widget _buildContent(BuildContext context) {
final List<Widget> children = <Widget>[];
if (title != null || content != null) {
final Widget titleSection = _CupertinoAlertContentSection(
title: title,
content: content,
scrollController: scrollController,
);
children.add(Flexible(flex: 3, child: titleSection));
}
final List<Widget> children = <Widget>[
if (title != null || content != null)
Flexible(
flex: 3,
child: _CupertinoAlertContentSection(
title: title,
content: content,
scrollController: scrollController,
),
),
];
return Container(
color: CupertinoDynamicColor.resolve(_kDialogColor, context),
@ -597,16 +598,10 @@ class _RenderCupertinoDialog extends RenderBox {
}
@override
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> value = <DiagnosticsNode>[];
if (contentSection != null) {
value.add(contentSection.toDiagnosticsNode(name: 'content'));
}
if (actionsSection != null) {
value.add(actionsSection.toDiagnosticsNode(name: 'actions'));
}
return value;
}
List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[
if (contentSection != null) contentSection.toDiagnosticsNode(name: 'content'),
if (actionsSection != null) actionsSection.toDiagnosticsNode(name: 'actions'),
];
@override
double computeMinIntrinsicWidth(double height) {

View File

@ -90,8 +90,6 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
@override
Widget build(BuildContext context) {
final List<Widget> stacked = <Widget>[];
Widget paddedContent = widget.child;
final MediaQueryData existingMediaQuery = MediaQuery.of(context);
@ -157,44 +155,40 @@ class _CupertinoPageScaffoldState extends State<CupertinoPageScaffold> {
);
}
// The main content being at the bottom is added to the stack first.
stacked.add(PrimaryScrollController(
controller: _primaryScrollController,
child: paddedContent,
));
if (widget.navigationBar != null) {
stacked.add(Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: MediaQuery(
data: existingMediaQuery.copyWith(textScaleFactor: 1),
child: widget.navigationBar,
),
));
}
// Add a touch handler the size of the status bar on top of all contents
// to handle scroll to top by status bar taps.
stacked.add(Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
height: existingMediaQuery.padding.top,
child: GestureDetector(
excludeFromSemantics: true,
onTap: _handleStatusBarTap,
),
),
);
return DecoratedBox(
decoration: BoxDecoration(
color: widget.backgroundColor ?? CupertinoTheme.of(context).scaffoldBackgroundColor,
),
child: Stack(
children: stacked,
children: <Widget>[
// The main content being at the bottom is added to the stack first.
PrimaryScrollController(
controller: _primaryScrollController,
child: paddedContent,
),
if (widget.navigationBar != null)
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: MediaQuery(
data: existingMediaQuery.copyWith(textScaleFactor: 1),
child: widget.navigationBar,
),
),
// Add a touch handler the size of the status bar on top of all contents
// to handle scroll to top by status bar taps.
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
height: existingMediaQuery.padding.top,
child: GestureDetector(
excludeFromSemantics: true,
onTap: _handleStatusBarTap,
),
),
],
),
);
}

View File

@ -346,8 +346,6 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
@override
Widget build(BuildContext context) {
final List<Widget> stacked = <Widget>[];
final MediaQueryData existingMediaQuery = MediaQuery.of(context);
MediaQueryData newMediaQuery = MediaQuery.of(context);
@ -397,36 +395,33 @@ class _CupertinoTabScaffoldState extends State<CupertinoTabScaffold> {
),
);
// The main content being at the bottom is added to the stack first.
stacked.add(content);
stacked.add(
MediaQuery(
data: existingMediaQuery.copyWith(textScaleFactor: 1),
child: Align(
alignment: Alignment.bottomCenter,
// Override the tab bar's currentIndex to the current tab and hook in
// our own listener to update the [_controller.currentIndex] on top of a possibly user
// provided callback.
child: widget.tabBar.copyWith(
currentIndex: _controller.index,
onTap: (int newIndex) {
_controller.index = newIndex;
// Chain the user's original callback.
if (widget.tabBar.onTap != null)
widget.tabBar.onTap(newIndex);
},
),
),
),
);
return DecoratedBox(
decoration: BoxDecoration(
color: widget.backgroundColor ?? CupertinoTheme.of(context).scaffoldBackgroundColor,
),
child: Stack(
children: stacked,
children: <Widget>[
// The main content being at the bottom is added to the stack first.
content,
MediaQuery(
data: existingMediaQuery.copyWith(textScaleFactor: 1),
child: Align(
alignment: Alignment.bottomCenter,
// Override the tab bar's currentIndex to the current tab and hook in
// our own listener to update the [_controller.currentIndex] on top of a possibly user
// provided callback.
child: widget.tabBar.copyWith(
currentIndex: _controller.index,
onTap: (int newIndex) {
_controller.index = newIndex;
// Chain the user's original callback.
if (widget.tabBar.onTap != null)
widget.tabBar.onTap(newIndex);
},
),
),
),
],
),
);
}

View File

@ -730,44 +730,38 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
valueListenable: _effectiveController,
child: editableText,
builder: (BuildContext context, TextEditingValue text, Widget child) {
final List<Widget> rowChildren = <Widget>[];
// Insert a prefix at the front if the prefix visibility mode matches
// the current text state.
if (_showPrefixWidget(text)) {
rowChildren.add(widget.prefix);
}
final List<Widget> stackChildren = <Widget>[];
// In the middle part, stack the placeholder on top of the main EditableText
// if needed.
if (widget.placeholder != null && text.text.isEmpty) {
stackChildren.add(
SizedBox(
width: double.infinity,
child: Padding(
padding: widget.padding,
child: Text(
widget.placeholder,
maxLines: widget.maxLines,
overflow: TextOverflow.ellipsis,
style: placeholderStyle,
textAlign: widget.textAlign,
),
),
return Row(children: <Widget>[
// Insert a prefix at the front if the prefix visibility mode matches
// the current text state.
if (_showPrefixWidget(text)) widget.prefix,
// In the middle part, stack the placeholder on top of the main EditableText
// if needed.
Expanded(
child: Stack(
children: <Widget>[
if (widget.placeholder != null && text.text.isEmpty)
SizedBox(
width: double.infinity,
child: Padding(
padding: widget.padding,
child: Text(
widget.placeholder,
maxLines: widget.maxLines,
overflow: TextOverflow.ellipsis,
style: placeholderStyle,
textAlign: widget.textAlign,
),
),
),
child,
],
),
);
}
rowChildren.add(Expanded(child: Stack(children: stackChildren..add(child))));
// First add the explicit suffix if the suffix visibility mode matches.
if (_showSuffixWidget(text)) {
rowChildren.add(widget.suffix);
// Otherwise, try to show a clear button if its visibility mode matches.
} else if (_showClearButton(text)) {
rowChildren.add(
),
// First add the explicit suffix if the suffix visibility mode matches.
if (_showSuffixWidget(text))
widget.suffix
// Otherwise, try to show a clear button if its visibility mode matches.
else if (_showClearButton(text))
GestureDetector(
key: _clearGlobalKey,
onTap: widget.enabled ?? true ? () {
@ -787,10 +781,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
),
),
),
);
}
return Row(children: rowChildren);
]);
},
);
}

View File

@ -547,9 +547,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
'(one line) summary description of the problem that was '
'detected.'
),
DiagnosticsProperty<FlutterError>('Malformed', this, expandableValue: true, showSeparator: false, style: DiagnosticsTreeStyle.whitespace),
ErrorDescription('\nThe malformed error has ${summaries.length} summaries.'),
];
message.add(DiagnosticsProperty<FlutterError>('Malformed', this, expandableValue: true, showSeparator: false, style: DiagnosticsTreeStyle.whitespace));
message.add(ErrorDescription('\nThe malformed error has ${summaries.length} summaries.'));
int i = 1;
for (DiagnosticsNode summary in summaries) {
message.add(DiagnosticsProperty<DiagnosticsNode>('Summary $i', summary, expandableValue : true));

View File

@ -552,10 +552,13 @@ class _AppBarState extends State<AppBar> {
child: appBar,
),
),
widget.bottomOpacity == 1.0 ? widget.bottom : Opacity(
opacity: const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.bottomOpacity),
child: widget.bottom,
),
if (widget.bottomOpacity == 1.0)
widget.bottom
else
Opacity(
opacity: const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.bottomOpacity),
child: widget.bottom,
),
],
);
}

View File

@ -303,22 +303,9 @@ class AlertDialog extends StatelessWidget {
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context);
final DialogTheme dialogTheme = DialogTheme.of(context);
final List<Widget> children = <Widget>[];
String label = semanticLabel;
if (title != null) {
children.add(Padding(
padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
child: DefaultTextStyle(
style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title,
child: Semantics(
child: title,
namesRoute: true,
container: true,
),
),
));
} else {
String label = semanticLabel;
if (title == null) {
switch (theme.platform) {
case TargetPlatform.iOS:
label = semanticLabel;
@ -329,29 +316,38 @@ class AlertDialog extends StatelessWidget {
}
}
if (content != null) {
children.add(Flexible(
child: Padding(
padding: contentPadding,
child: DefaultTextStyle(
style: contentTextStyle ?? dialogTheme.contentTextStyle ?? theme.textTheme.subhead,
child: content,
),
),
));
}
if (actions != null) {
children.add(ButtonBar(
children: actions,
));
}
Widget dialogChild = IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children,
children: <Widget>[
if (title != null)
Padding(
padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
child: DefaultTextStyle(
style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title,
child: Semantics(
child: title,
namesRoute: true,
container: true,
),
),
),
if (content != null)
Flexible(
child: Padding(
padding: contentPadding,
child: DefaultTextStyle(
style: contentTextStyle ?? dialogTheme.contentTextStyle ?? theme.textTheme.subhead,
child: content,
),
),
),
if (actions != null)
ButtonBar(
children: actions,
),
],
),
);
@ -584,20 +580,10 @@ class SimpleDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context));
final List<Widget> body = <Widget>[];
String label = semanticLabel;
final ThemeData theme = Theme.of(context);
if (title != null) {
body.add(Padding(
padding: titlePadding,
child: DefaultTextStyle(
style: theme.textTheme.title,
child: Semantics(namesRoute: true, child: title),
),
));
} else {
String label = semanticLabel;
if (title == null) {
switch (theme.platform) {
case TargetPlatform.iOS:
label = semanticLabel;
@ -608,15 +594,6 @@ class SimpleDialog extends StatelessWidget {
}
}
if (children != null) {
body.add(Flexible(
child: SingleChildScrollView(
padding: contentPadding,
child: ListBody(children: children),
),
));
}
Widget dialogChild = IntrinsicWidth(
stepWidth: 56.0,
child: ConstrainedBox(
@ -624,7 +601,23 @@ class SimpleDialog extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: body,
children: <Widget>[
if (title != null)
Padding(
padding: titlePadding,
child: DefaultTextStyle(
style: theme.textTheme.title,
child: Semantics(namesRoute: true, child: title),
),
),
if (children != null)
Flexible(
child: SingleChildScrollView(
padding: contentPadding,
child: ListBody(children: children),
),
),
],
),
),
);

View File

@ -951,9 +951,10 @@ class _DropdownButtonState<T> extends State<DropdownButton<T>> with WidgetsBindi
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
widget.isExpanded
? Expanded(child: innerItemsWidget)
: innerItemsWidget,
if (widget.isExpanded)
Expanded(child: innerItemsWidget)
else
innerItemsWidget,
IconTheme(
data: IconThemeData(
color: _iconColor,

View File

@ -48,27 +48,26 @@ class GridTile extends StatelessWidget {
if (header == null && footer == null)
return child;
final List<Widget> children = <Widget>[
Positioned.fill(
child: child,
),
];
if (header != null) {
children.add(Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: header,
));
}
if (footer != null) {
children.add(Positioned(
left: 0.0,
bottom: 0.0,
right: 0.0,
child: footer,
));
}
return Stack(children: children);
return Stack(
children: <Widget>[
Positioned.fill(
child: child,
),
if (header != null)
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: header,
),
if (footer != null)
Positioned(
left: 0.0,
bottom: 0.0,
right: 0.0,
child: footer,
),
],
);
}
}

View File

@ -62,60 +62,17 @@ class GridTileBar extends StatelessWidget {
if (backgroundColor != null)
decoration = BoxDecoration(color: backgroundColor);
final List<Widget> children = <Widget>[];
final EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(
start: leading != null ? 8.0 : 16.0,
end: trailing != null ? 8.0 : 16.0,
);
if (leading != null)
children.add(Padding(padding: const EdgeInsetsDirectional.only(end: 8.0), child: leading));
final ThemeData theme = Theme.of(context);
final ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
accentColor: theme.accentColor,
accentColorBrightness: theme.accentColorBrightness,
);
if (title != null && subtitle != null) {
children.add(
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
DefaultTextStyle(
style: darkTheme.textTheme.subhead,
softWrap: false,
overflow: TextOverflow.ellipsis,
child: title,
),
DefaultTextStyle(
style: darkTheme.textTheme.caption,
softWrap: false,
overflow: TextOverflow.ellipsis,
child: subtitle,
),
],
),
)
);
} else if (title != null || subtitle != null) {
children.add(
Expanded(
child: DefaultTextStyle(
style: darkTheme.textTheme.subhead,
softWrap: false,
overflow: TextOverflow.ellipsis,
child: title ?? subtitle,
),
)
);
}
if (trailing != null)
children.add(Padding(padding: const EdgeInsetsDirectional.only(start: 8.0), child: trailing));
return Container(
padding: padding,
decoration: decoration,
@ -126,7 +83,42 @@ class GridTileBar extends StatelessWidget {
data: const IconThemeData(color: Colors.white),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
children: <Widget>[
if (leading != null)
Padding(padding: const EdgeInsetsDirectional.only(end: 8.0), child: leading),
if (title != null && subtitle != null)
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
DefaultTextStyle(
style: darkTheme.textTheme.subhead,
softWrap: false,
overflow: TextOverflow.ellipsis,
child: title,
),
DefaultTextStyle(
style: darkTheme.textTheme.caption,
softWrap: false,
overflow: TextOverflow.ellipsis,
child: subtitle,
),
],
),
)
else if (title != null || subtitle != null)
Expanded(
child: DefaultTextStyle(
style: darkTheme.textTheme.subhead,
softWrap: false,
overflow: TextOverflow.ellipsis,
child: title ?? subtitle,
),
),
if (trailing != null)
Padding(padding: const EdgeInsetsDirectional.only(start: 8.0), child: trailing),
],
),
),
),

View File

@ -433,17 +433,13 @@ class InkResponse extends StatefulWidget {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
final List<String> gestures = <String>[];
if (onTap != null)
gestures.add('tap');
if (onDoubleTap != null)
gestures.add('double tap');
if (onLongPress != null)
gestures.add('long press');
if (onTapDown != null)
gestures.add('tap down');
if (onTapCancel != null)
gestures.add('tap cancel');
final List<String> gestures = <String>[
if (onTap != null) 'tap',
if (onDoubleTap != null) 'double tap',
if (onLongPress != null) 'long press',
if (onTapDown != null) 'tap down',
if (onTapCancel != null) 'tap cancel',
];
properties.add(IterableProperty<String>('gestures', gestures, ifEmpty: '<none>'));
properties.add(DiagnosticsProperty<bool>('containedInkWell', containedInkWell, level: DiagnosticLevel.fine));
properties.add(DiagnosticsProperty<BoxShape>(

View File

@ -3145,79 +3145,44 @@ class InputDecoration {
@override
String toString() {
final List<String> description = <String>[];
if (icon != null)
description.add('icon: $icon');
if (labelText != null)
description.add('labelText: "$labelText"');
if (helperText != null)
description.add('helperText: "$helperText"');
if (hintText != null)
description.add('hintText: "$hintText"');
if (hintMaxLines != null)
description.add('hintMaxLines: "$hintMaxLines"');
if (errorText != null)
description.add('errorText: "$errorText"');
if (errorStyle != null)
description.add('errorStyle: "$errorStyle"');
if (errorMaxLines != null)
description.add('errorMaxLines: "$errorMaxLines"');
if (hasFloatingPlaceholder == false)
description.add('hasFloatingPlaceholder: false');
if (isDense ?? false)
description.add('isDense: $isDense');
if (contentPadding != null)
description.add('contentPadding: $contentPadding');
if (isCollapsed)
description.add('isCollapsed: $isCollapsed');
if (prefixIcon != null)
description.add('prefixIcon: $prefixIcon');
if (prefix != null)
description.add('prefix: $prefix');
if (prefixText != null)
description.add('prefixText: $prefixText');
if (prefixStyle != null)
description.add('prefixStyle: $prefixStyle');
if (suffixIcon != null)
description.add('suffixIcon: $suffixIcon');
if (suffix != null)
description.add('suffix: $suffix');
if (suffixText != null)
description.add('suffixText: $suffixText');
if (suffixStyle != null)
description.add('suffixStyle: $suffixStyle');
if (counter != null)
description.add('counter: $counter');
if (counterText != null)
description.add('counterText: $counterText');
if (counterStyle != null)
description.add('counterStyle: $counterStyle');
if (filled == true) // filled == null same as filled == false
description.add('filled: true');
if (fillColor != null)
description.add('fillColor: $fillColor');
if (focusColor != null)
description.add('focusColor: $focusColor');
if (hoverColor != null)
description.add('hoverColor: $hoverColor');
if (errorBorder != null)
description.add('errorBorder: $errorBorder');
if (focusedBorder != null)
description.add('focusedBorder: $focusedBorder');
if (focusedErrorBorder != null)
description.add('focusedErrorBorder: $focusedErrorBorder');
if (disabledBorder != null)
description.add('disabledBorder: $disabledBorder');
if (enabledBorder != null)
description.add('enabledBorder: $enabledBorder');
if (border != null)
description.add('border: $border');
if (!enabled)
description.add('enabled: false');
if (semanticCounterText != null)
description.add('semanticCounterText: $semanticCounterText');
if (alignLabelWithHint != null)
description.add('alignLabelWithHint: $alignLabelWithHint');
final List<String> description = <String>[
if (icon != null) 'icon: $icon',
if (labelText != null) 'labelText: "$labelText"',
if (helperText != null) 'helperText: "$helperText"',
if (hintText != null) 'hintText: "$hintText"',
if (hintMaxLines != null) 'hintMaxLines: "$hintMaxLines"',
if (errorText != null) 'errorText: "$errorText"',
if (errorStyle != null) 'errorStyle: "$errorStyle"',
if (errorMaxLines != null) 'errorMaxLines: "$errorMaxLines"',
if (hasFloatingPlaceholder == false) 'hasFloatingPlaceholder: false',
if (isDense ?? false) 'isDense: $isDense',
if (contentPadding != null) 'contentPadding: $contentPadding',
if (isCollapsed) 'isCollapsed: $isCollapsed',
if (prefixIcon != null) 'prefixIcon: $prefixIcon',
if (prefix != null) 'prefix: $prefix',
if (prefixText != null) 'prefixText: $prefixText',
if (prefixStyle != null) 'prefixStyle: $prefixStyle',
if (suffixIcon != null) 'suffixIcon: $suffixIcon',
if (suffix != null) 'suffix: $suffix',
if (suffixText != null) 'suffixText: $suffixText',
if (suffixStyle != null) 'suffixStyle: $suffixStyle',
if (counter != null) 'counter: $counter',
if (counterText != null) 'counterText: $counterText',
if (counterStyle != null) 'counterStyle: $counterStyle',
if (filled == true) 'filled: true', // filled == null same as filled == false
if (fillColor != null) 'fillColor: $fillColor',
if (focusColor != null) 'focusColor: $focusColor',
if (hoverColor != null) 'hoverColor: $hoverColor',
if (errorBorder != null) 'errorBorder: $errorBorder',
if (focusedBorder != null) 'focusedBorder: $focusedBorder',
if (focusedErrorBorder != null) 'focusedErrorBorder: $focusedErrorBorder',
if (disabledBorder != null) 'disabledBorder: $disabledBorder',
if (enabledBorder != null) 'enabledBorder: $enabledBorder',
if (border != null) 'border: $border',
if (!enabled) 'enabled: false',
if (semanticCounterText != null) 'semanticCounterText: $semanticCounterText',
if (alignLabelWithHint != null) 'alignLabelWithHint: $alignLabelWithHint',
];
return 'InputDecoration(${description.join(', ')})';
}
}

View File

@ -538,13 +538,6 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
assert(debugCheckHasMaterialLocalizations(context));
// We use the layout builder to constrain the cross-axis size of dragging child widgets.
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
final List<Widget> wrappedChildren = <Widget>[];
if (widget.header != null) {
wrappedChildren.add(widget.header);
}
for (int i = 0; i < widget.children.length; i += 1) {
wrappedChildren.add(_wrap(widget.children[i], i, constraints));
}
const Key endWidgetKey = Key('DraggableList - End Widget');
Widget finalDropArea;
switch (widget.scrollDirection) {
@ -564,25 +557,19 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
);
break;
}
if (widget.reverse) {
wrappedChildren.insert(0, _wrap(
finalDropArea,
widget.children.length,
constraints),
);
} else {
wrappedChildren.add(_wrap(
finalDropArea,
widget.children.length,
constraints),
);
}
return SingleChildScrollView(
scrollDirection: widget.scrollDirection,
child: _buildContainerForScrollDirection(children: wrappedChildren),
padding: widget.padding,
controller: _scrollController,
reverse: widget.reverse,
child: _buildContainerForScrollDirection(
children: <Widget>[
if (widget.reverse) _wrap(finalDropArea, widget.children.length, constraints),
if (widget.header != null) widget.header,
for (int i = 0; i < widget.children.length; i += 1) _wrap(widget.children[i], i, constraints),
if (!widget.reverse) _wrap(finalDropArea, widget.children.length, constraints),
],
),
);
});
}

View File

@ -749,46 +749,40 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
@override
Widget build(BuildContext context) {
final List<Widget> children = <Widget>[];
if (_previousController.status != AnimationStatus.dismissed) {
if (_isExtendedFloatingActionButton(_previousChild)) {
children.add(FadeTransition(
opacity: _previousScaleAnimation,
child: _previousChild,
));
} else {
children.add(ScaleTransition(
scale: _previousScaleAnimation,
child: RotationTransition(
turns: _previousRotationAnimation,
child: _previousChild,
),
));
}
}
if (_isExtendedFloatingActionButton(widget.child)) {
children.add(ScaleTransition(
scale: _extendedCurrentScaleAnimation,
child: FadeTransition(
opacity: _currentScaleAnimation,
child: widget.child,
),
));
} else {
children.add(ScaleTransition(
scale: _currentScaleAnimation,
child: RotationTransition(
turns: _currentRotationAnimation,
child: widget.child,
),
));
}
return Stack(
alignment: Alignment.centerRight,
children: children,
children: <Widget>[
if (_previousController.status != AnimationStatus.dismissed)
if (_isExtendedFloatingActionButton(_previousChild))
FadeTransition(
opacity: _previousScaleAnimation,
child: _previousChild,
)
else
ScaleTransition(
scale: _previousScaleAnimation,
child: RotationTransition(
turns: _previousRotationAnimation,
child: _previousChild,
),
),
if (_isExtendedFloatingActionButton(widget.child))
ScaleTransition(
scale: _extendedCurrentScaleAnimation,
child: FadeTransition(
opacity: _currentScaleAnimation,
child: widget.child,
),
)
else
ScaleTransition(
scale: _currentScaleAnimation,
child: RotationTransition(
turns: _currentRotationAnimation,
child: widget.child,
),
),
],
);
}

View File

@ -288,28 +288,6 @@ class SnackBar extends StatelessWidget {
final bool isFloatingSnackBar = snackBarBehavior == SnackBarBehavior.floating;
final double snackBarPadding = isFloatingSnackBar ? 16.0 : 24.0;
final List<Widget> children = <Widget>[
SizedBox(width: snackBarPadding),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(vertical: _singleLineVerticalPadding),
child: DefaultTextStyle(
style: contentTextStyle,
child: content,
),
),
),
];
if (action != null) {
children.add(ButtonTheme(
textTheme: ButtonTextTheme.accent,
minWidth: 64.0,
padding: EdgeInsets.symmetric(horizontal: snackBarPadding),
child: action,
));
} else {
children.add(SizedBox(width: snackBarPadding));
}
final CurvedAnimation heightAnimation = CurvedAnimation(parent: animation, curve: _snackBarHeightCurve);
final CurvedAnimation fadeInAnimation = CurvedAnimation(parent: animation, curve: _snackBarFadeInCurve);
final CurvedAnimation fadeOutAnimation = CurvedAnimation(
@ -322,8 +300,28 @@ class SnackBar extends StatelessWidget {
top: false,
bottom: !isFloatingSnackBar,
child: Row(
children: children,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(width: snackBarPadding),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(vertical: _singleLineVerticalPadding),
child: DefaultTextStyle(
style: contentTextStyle,
child: content,
),
),
),
if (action != null)
ButtonTheme(
textTheme: ButtonTextTheme.accent,
minWidth: 64.0,
padding: EdgeInsets.symmetric(horizontal: snackBarPadding),
child: action,
)
else
SizedBox(width: snackBarPadding),
],
),
);

View File

@ -480,32 +480,27 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
}
Widget _buildHeaderText(int index) {
final List<Widget> children = <Widget>[
AnimatedDefaultTextStyle(
style: _titleStyle(index),
duration: kThemeAnimationDuration,
curve: Curves.fastOutSlowIn,
child: widget.steps[index].title,
),
];
if (widget.steps[index].subtitle != null)
children.add(
Container(
margin: const EdgeInsets.only(top: 2.0),
child: AnimatedDefaultTextStyle(
style: _subtitleStyle(index),
duration: kThemeAnimationDuration,
curve: Curves.fastOutSlowIn,
child: widget.steps[index].subtitle,
),
),
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: children,
children: <Widget>[
AnimatedDefaultTextStyle(
style: _titleStyle(index),
duration: kThemeAnimationDuration,
curve: Curves.fastOutSlowIn,
child: widget.steps[index].title,
),
if (widget.steps[index].subtitle != null)
Container(
margin: const EdgeInsets.only(top: 2.0),
child: AnimatedDefaultTextStyle(
style: _subtitleStyle(index),
duration: kThemeAnimationDuration,
curve: Curves.fastOutSlowIn,
child: widget.steps[index].subtitle,
),
),
],
);
}
@ -577,46 +572,39 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
}
Widget _buildVertical() {
final List<Widget> children = <Widget>[];
for (int i = 0; i < widget.steps.length; i += 1) {
children.add(
Column(
key: _keys[i],
children: <Widget>[
InkWell(
onTap: widget.steps[i].state != StepState.disabled ? () {
// In the vertical case we need to scroll to the newly tapped
// step.
Scrollable.ensureVisible(
_keys[i].currentContext,
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
);
if (widget.onStepTapped != null)
widget.onStepTapped(i);
} : null,
child: _buildVerticalHeader(i),
),
_buildVerticalBody(i),
],
)
);
}
return ListView(
shrinkWrap: true,
physics: widget.physics,
children: children,
children: <Widget>[
for (int i = 0; i < widget.steps.length; i += 1)
Column(
key: _keys[i],
children: <Widget>[
InkWell(
onTap: widget.steps[i].state != StepState.disabled ? () {
// In the vertical case we need to scroll to the newly tapped
// step.
Scrollable.ensureVisible(
_keys[i].currentContext,
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
);
if (widget.onStepTapped != null)
widget.onStepTapped(i);
} : null,
child: _buildVerticalHeader(i),
),
_buildVerticalBody(i),
],
),
],
);
}
Widget _buildHorizontal() {
final List<Widget> children = <Widget>[];
for (int i = 0; i < widget.steps.length; i += 1) {
children.add(
final List<Widget> children = <Widget>[
for (int i = 0; i < widget.steps.length; i += 1) ...<Widget>[
InkResponse(
onTap: widget.steps[i].state != StepState.disabled ? () {
if (widget.onStepTapped != null)
@ -637,10 +625,7 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
],
),
),
);
if (!_isLast(i)) {
children.add(
if (!_isLast(i))
Expanded(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
@ -648,9 +633,8 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
color: Colors.grey.shade400,
),
),
);
}
}
],
];
return Column(
children: <Widget>[

View File

@ -40,17 +40,13 @@ class _TextSelectionToolbar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List<Widget> items = <Widget>[];
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
if (handleCut != null)
items.add(FlatButton(child: Text(localizations.cutButtonLabel), onPressed: handleCut));
if (handleCopy != null)
items.add(FlatButton(child: Text(localizations.copyButtonLabel), onPressed: handleCopy));
if (handlePaste != null)
items.add(FlatButton(child: Text(localizations.pasteButtonLabel), onPressed: handlePaste,));
if (handleSelectAll != null)
items.add(FlatButton(child: Text(localizations.selectAllButtonLabel), onPressed: handleSelectAll));
final List<Widget> items = <Widget>[
if (handleCut != null) FlatButton(child: Text(localizations.cutButtonLabel), onPressed: handleCut),
if (handleCopy != null) FlatButton(child: Text(localizations.copyButtonLabel), onPressed: handleCopy),
if (handlePaste != null) FlatButton(child: Text(localizations.pasteButtonLabel), onPressed: handlePaste),
if (handleSelectAll != null) FlatButton(child: Text(localizations.selectAllButtonLabel), onPressed: handleSelectAll),
];
// If there is no option available, build an empty widget.
if (items.isEmpty) {

View File

@ -541,12 +541,13 @@ _TimePickerHeaderFormat _buildHeaderFormat(
_TimePickerHeaderFragment fragment2,
_TimePickerHeaderFragment fragment3,
}) {
final List<_TimePickerHeaderFragment> fragments = <_TimePickerHeaderFragment>[fragment1];
if (fragment2 != null) {
fragments.add(fragment2);
if (fragment3 != null)
fragments.add(fragment3);
}
final List<_TimePickerHeaderFragment> fragments = <_TimePickerHeaderFragment>[
fragment1,
if (fragment2 != null) ...<_TimePickerHeaderFragment>[
fragment2,
if (fragment3 != null) fragment3,
],
];
return _TimePickerHeaderPiece(pivotIndex, fragments, bottomMargin: bottomMargin);
}
@ -1336,50 +1337,41 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin {
);
}
List<_TappableLabel> _build24HourInnerRing(TextTheme textTheme) {
final List<_TappableLabel> labels = <_TappableLabel>[];
for (TimeOfDay timeOfDay in _amHours) {
labels.add(_buildTappableLabel(
List<_TappableLabel> _build24HourInnerRing(TextTheme textTheme) => <_TappableLabel>[
for (TimeOfDay timeOfDay in _amHours)
_buildTappableLabel(
textTheme,
timeOfDay.hour,
localizations.formatHour(timeOfDay, alwaysUse24HourFormat: media.alwaysUse24HourFormat),
() {
_selectHour(timeOfDay.hour);
},
));
}
return labels;
}
),
];
List<_TappableLabel> _build24HourOuterRing(TextTheme textTheme) {
final List<_TappableLabel> labels = <_TappableLabel>[];
for (TimeOfDay timeOfDay in _pmHours) {
labels.add(_buildTappableLabel(
List<_TappableLabel> _build24HourOuterRing(TextTheme textTheme) => <_TappableLabel>[
for (TimeOfDay timeOfDay in _pmHours)
_buildTappableLabel(
textTheme,
timeOfDay.hour,
localizations.formatHour(timeOfDay, alwaysUse24HourFormat: media.alwaysUse24HourFormat),
() {
_selectHour(timeOfDay.hour);
},
));
}
return labels;
}
),
];
List<_TappableLabel> _build12HourOuterRing(TextTheme textTheme) {
final List<_TappableLabel> labels = <_TappableLabel>[];
for (TimeOfDay timeOfDay in _amHours) {
labels.add(_buildTappableLabel(
List<_TappableLabel> _build12HourOuterRing(TextTheme textTheme) => <_TappableLabel>[
for (TimeOfDay timeOfDay in _amHours)
_buildTappableLabel(
textTheme,
timeOfDay.hour,
localizations.formatHour(timeOfDay, alwaysUse24HourFormat: media.alwaysUse24HourFormat),
() {
_selectHour(timeOfDay.hour);
},
));
}
return labels;
}
),
];
List<_TappableLabel> _buildMinutes(TextTheme textTheme) {
const List<TimeOfDay> _minuteMarkerValues = <TimeOfDay>[
@ -1397,18 +1389,17 @@ class _DialState extends State<_Dial> with SingleTickerProviderStateMixin {
TimeOfDay(hour: 0, minute: 55),
];
final List<_TappableLabel> labels = <_TappableLabel>[];
for (TimeOfDay timeOfDay in _minuteMarkerValues) {
labels.add(_buildTappableLabel(
textTheme,
timeOfDay.minute,
localizations.formatMinute(timeOfDay),
() {
_selectMinute(timeOfDay.minute);
},
));
}
return labels;
return <_TappableLabel>[
for (TimeOfDay timeOfDay in _minuteMarkerValues)
_buildTappableLabel(
textTheme,
timeOfDay.minute,
localizations.formatMinute(timeOfDay),
() {
_selectMinute(timeOfDay.minute);
},
),
];
}
@override

View File

@ -134,71 +134,63 @@ class _AccountDetailsState extends State<_AccountDetails> with SingleTickerProvi
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context);
final List<Widget> children = <Widget>[];
if (widget.accountName != null) {
final Widget accountNameLine = LayoutId(
id: _AccountDetailsLayout.accountName,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: DefaultTextStyle(
style: theme.primaryTextTheme.body2,
overflow: TextOverflow.ellipsis,
child: widget.accountName,
),
),
);
children.add(accountNameLine);
}
if (widget.accountEmail != null) {
final Widget accountEmailLine = LayoutId(
id: _AccountDetailsLayout.accountEmail,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: DefaultTextStyle(
style: theme.primaryTextTheme.body1,
overflow: TextOverflow.ellipsis,
child: widget.accountEmail,
),
),
);
children.add(accountEmailLine);
}
if (widget.onTap != null) {
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final Widget dropDownIcon = LayoutId(
id: _AccountDetailsLayout.dropdownIcon,
child: Semantics(
container: true,
button: true,
onTap: widget.onTap,
child: SizedBox(
height: _kAccountDetailsHeight,
width: _kAccountDetailsHeight,
child: Center(
child: Transform.rotate(
angle: _animation.value * math.pi,
child: Icon(
Icons.arrow_drop_down,
color: widget.arrowColor,
semanticLabel: widget.isOpen
? localizations.hideAccountsLabel
: localizations.showAccountsLabel,
),
),
),
),
),
);
children.add(dropDownIcon);
}
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
Widget accountDetails = CustomMultiChildLayout(
delegate: _AccountDetailsLayout(
textDirection: Directionality.of(context),
),
children: children,
children: <Widget>[
if (widget.accountName != null)
LayoutId(
id: _AccountDetailsLayout.accountName,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: DefaultTextStyle(
style: theme.primaryTextTheme.body2,
overflow: TextOverflow.ellipsis,
child: widget.accountName,
),
),
),
if (widget.accountEmail != null)
LayoutId(
id: _AccountDetailsLayout.accountEmail,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 2.0),
child: DefaultTextStyle(
style: theme.primaryTextTheme.body1,
overflow: TextOverflow.ellipsis,
child: widget.accountEmail,
),
),
),
if (widget.onTap != null)
LayoutId(
id: _AccountDetailsLayout.dropdownIcon,
child: Semantics(
container: true,
button: true,
onTap: widget.onTap,
child: SizedBox(
height: _kAccountDetailsHeight,
width: _kAccountDetailsHeight,
child: Center(
child: Transform.rotate(
angle: _animation.value * math.pi,
child: Icon(
Icons.arrow_drop_down,
color: widget.arrowColor,
semanticLabel: widget.isOpen
? localizations.hideAccountsLabel
: localizations.showAccountsLabel,
),
),
),
),
),
),
],
);
if (widget.onTap != null) {

View File

@ -533,15 +533,12 @@ class Border extends BoxBorder {
String toString() {
if (isUniform)
return '$runtimeType.all($top)';
final List<String> arguments = <String>[];
if (top != BorderSide.none)
arguments.add('top: $top');
if (right != BorderSide.none)
arguments.add('right: $right');
if (bottom != BorderSide.none)
arguments.add('bottom: $bottom');
if (left != BorderSide.none)
arguments.add('left: $left');
final List<String> arguments = <String>[
if (top != BorderSide.none) 'top: $top',
if (right != BorderSide.none) 'right: $right',
if (bottom != BorderSide.none) 'bottom: $bottom',
if (left != BorderSide.none) 'left: $left',
];
return '$runtimeType(${arguments.join(", ")})';
}
}
@ -838,15 +835,12 @@ class BorderDirectional extends BoxBorder {
@override
String toString() {
final List<String> arguments = <String>[];
if (top != BorderSide.none)
arguments.add('top: $top');
if (start != BorderSide.none)
arguments.add('start: $start');
if (end != BorderSide.none)
arguments.add('end: $end');
if (bottom != BorderSide.none)
arguments.add('bottom: $bottom');
final List<String> arguments = <String>[
if (top != BorderSide.none) 'top: $top',
if (start != BorderSide.none) 'start: $start',
if (end != BorderSide.none) 'end: $end',
if (bottom != BorderSide.none) 'bottom: $bottom',
];
return '$runtimeType(${arguments.join(", ")})';
}
}

View File

@ -104,15 +104,12 @@ class BoxShadow extends ui.Shadow {
return null;
a ??= <BoxShadow>[];
b ??= <BoxShadow>[];
final List<BoxShadow> result = <BoxShadow>[];
final int commonLength = math.min(a.length, b.length);
for (int i = 0; i < commonLength; i += 1)
result.add(BoxShadow.lerp(a[i], b[i], t));
for (int i = commonLength; i < a.length; i += 1)
result.add(a[i].scale(1.0 - t));
for (int i = commonLength; i < b.length; i += 1)
result.add(b[i].scale(t));
return result;
return <BoxShadow>[
for (int i = 0; i < commonLength; i += 1) BoxShadow.lerp(a[i], b[i], t),
for (int i = commonLength; i < a.length; i += 1) a[i].scale(1.0 - t),
for (int i = commonLength; i < b.length; i += 1) b[i].scale(t),
];
}
@override

View File

@ -156,21 +156,22 @@ class DecorationImage {
@override
String toString() {
final List<String> properties = <String>[];
properties.add('$image');
if (colorFilter != null)
properties.add('$colorFilter');
if (fit != null &&
!(fit == BoxFit.fill && centerSlice != null) &&
!(fit == BoxFit.scaleDown && centerSlice == null))
properties.add('$fit');
properties.add('$alignment');
if (centerSlice != null)
properties.add('centerSlice: $centerSlice');
if (repeat != ImageRepeat.noRepeat)
properties.add('$repeat');
if (matchTextDirection)
properties.add('match text direction');
final List<String> properties = <String>[
'$image',
if (colorFilter != null)
'$colorFilter',
if (fit != null &&
!(fit == BoxFit.fill && centerSlice != null) &&
!(fit == BoxFit.scaleDown && centerSlice == null))
'$fit',
'$alignment',
if (centerSlice != null)
'centerSlice: $centerSlice',
if (repeat != ImageRepeat.noRepeat)
'$repeat',
if (matchTextDirection)
'match text direction',
];
return '$runtimeType(${properties.join(", ")})';
}
}

View File

@ -578,10 +578,11 @@ class StrutStyle extends Diagnosticable {
super.debugFillProperties(properties);
if (debugLabel != null)
properties.add(MessageProperty('${prefix}debugLabel', debugLabel));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[];
styles.add(StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false));
styles.add(IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null));
styles.add(DoubleProperty('${prefix}size', fontSize, defaultValue: null));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[
StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false),
IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null),
DoubleProperty('${prefix}size', fontSize, defaultValue: null),
];
String weightDescription;
if (fontWeight != null) {
weightDescription = 'w${fontWeight.index + 1}00';

View File

@ -1202,12 +1202,13 @@ class TextStyle extends Diagnosticable {
super.debugFillProperties(properties);
if (debugLabel != null)
properties.add(MessageProperty('${prefix}debugLabel', debugLabel));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[];
styles.add(ColorProperty('${prefix}color', color, defaultValue: null));
styles.add(ColorProperty('${prefix}backgroundColor', backgroundColor, defaultValue: null));
styles.add(StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false));
styles.add(IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null));
styles.add(DoubleProperty('${prefix}size', fontSize, defaultValue: null));
final List<DiagnosticsNode> styles = <DiagnosticsNode>[
ColorProperty('${prefix}color', color, defaultValue: null),
ColorProperty('${prefix}backgroundColor', backgroundColor, defaultValue: null),
StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false),
IterableProperty<String>('${prefix}familyFallback', fontFamilyFallback, defaultValue: null),
DoubleProperty('${prefix}size', fontSize, defaultValue: null),
];
String weightDescription;
if (fontWeight != null) {
weightDescription = '${fontWeight.index + 1}00';

View File

@ -505,15 +505,12 @@ class BoxConstraints extends Constraints {
]);
}
if (minWidth.isNaN || maxWidth.isNaN || minHeight.isNaN || maxHeight.isNaN) {
final List<String> affectedFieldsList = <String>[];
if (minWidth.isNaN)
affectedFieldsList.add('minWidth');
if (maxWidth.isNaN)
affectedFieldsList.add('maxWidth');
if (minHeight.isNaN)
affectedFieldsList.add('minHeight');
if (maxHeight.isNaN)
affectedFieldsList.add('maxHeight');
final List<String> affectedFieldsList = <String>[
if (minWidth.isNaN) 'minWidth',
if (maxWidth.isNaN) 'maxWidth',
if (minHeight.isNaN) 'minHeight',
if (maxHeight.isNaN) 'maxHeight',
];
assert(affectedFieldsList.isNotEmpty);
if (affectedFieldsList.length > 1)
affectedFieldsList.add('and ${affectedFieldsList.removeLast()}');
@ -1711,8 +1708,9 @@ abstract class RenderBox extends RenderObject {
(!sizedByParent && debugDoingThisLayout))
return true;
assert(!debugDoingThisResize);
final List<DiagnosticsNode> information = <DiagnosticsNode>[];
information.add(ErrorSummary('RenderBox size setter called incorrectly.'));
final List<DiagnosticsNode> information = <DiagnosticsNode>[
ErrorSummary('RenderBox size setter called incorrectly.'),
];
if (debugDoingThisLayout) {
assert(sizedByParent);
information.add(ErrorDescription('It appears that the size setter was called from performLayout().'));

View File

@ -217,15 +217,12 @@ mixin DebugOverflowIndicatorMixin on RenderObject {
));
}
final List<String> overflows = <String>[];
if (overflow.left > 0.0)
overflows.add('${_formatPixels(overflow.left)} pixels on the left');
if (overflow.top > 0.0)
overflows.add('${_formatPixels(overflow.top)} pixels on the top');
if (overflow.bottom > 0.0)
overflows.add('${_formatPixels(overflow.bottom)} pixels on the bottom');
if (overflow.right > 0.0)
overflows.add('${_formatPixels(overflow.right)} pixels on the right');
final List<String> overflows = <String>[
if (overflow.left > 0.0) '${_formatPixels(overflow.left)} pixels on the left',
if (overflow.top > 0.0) '${_formatPixels(overflow.top)} pixels on the top',
if (overflow.bottom > 0.0) '${_formatPixels(overflow.bottom)} pixels on the bottom',
if (overflow.right > 0.0) '${_formatPixels(overflow.right)} pixels on the right',
];
String overflowText = '';
assert(overflows.isNotEmpty,
"Somehow $runtimeType didn't actually overflow like it thought it did.");

View File

@ -44,12 +44,11 @@ class TextParentData extends ContainerBoxParentData<RenderBox> {
@override
String toString() {
final List<String> values = <String>[];
if (offset != null)
values.add('offset=$offset');
if (scale != null)
values.add('scale=$scale');
values.add(super.toString());
final List<String> values = <String>[
if (offset != null) 'offset=$offset',
if (scale != null) 'scale=$scale',
super.toString(),
];
return values.join('; ');
}
}

View File

@ -3456,15 +3456,12 @@ class RenderSemanticsGestureHandler extends RenderProxyBox {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
final List<String> gestures = <String>[];
if (onTap != null)
gestures.add('tap');
if (onLongPress != null)
gestures.add('long press');
if (onHorizontalDragUpdate != null)
gestures.add('horizontal scroll');
if (onVerticalDragUpdate != null)
gestures.add('vertical scroll');
final List<String> gestures = <String>[
if (onTap != null) 'tap',
if (onLongPress != null) 'long press',
if (onHorizontalDragUpdate != null) 'horizontal scroll',
if (onVerticalDragUpdate != null) 'vertical scroll',
];
if (gestures.isEmpty)
gestures.add('<none>');
properties.add(IterableProperty<String>('gestures', gestures));

View File

@ -953,21 +953,20 @@ class SliverPhysicalParentData extends ParentData {
class SliverPhysicalContainerParentData extends SliverPhysicalParentData with ContainerParentDataMixin<RenderSliver> { }
List<DiagnosticsNode> _debugCompareFloats(String labelA, double valueA, String labelB, double valueB) {
final List<DiagnosticsNode> information = <DiagnosticsNode>[];
if (valueA.toStringAsFixed(1) != valueB.toStringAsFixed(1)) {
information..add(ErrorDescription(
'The $labelA is ${valueA.toStringAsFixed(1)}, but '
'the $labelB is ${valueB.toStringAsFixed(1)}.'
));
} else {
information
..add(ErrorDescription('The $labelA is $valueA, but the $labelB is $valueB.'))
..add(ErrorHint(
return <DiagnosticsNode>[
if (valueA.toStringAsFixed(1) != valueB.toStringAsFixed(1))
ErrorDescription(
'The $labelA is ${valueA.toStringAsFixed(1)}, but '
'the $labelB is ${valueB.toStringAsFixed(1)}.'
)
else ...<DiagnosticsNode>[
ErrorDescription('The $labelA is $valueA, but the $labelB is $valueB.'),
ErrorHint(
'Maybe you have fallen prey to floating point rounding errors, and should explicitly '
'apply the min() or max() functions, or the clamp() method, to the $labelB?'
));
}
return information;
),
],
];
}
/// Base class for the render objects that implement scroll effects in viewports.
@ -1146,13 +1145,11 @@ abstract class RenderSliver extends RenderObject {
final List<DiagnosticsNode> information = <DiagnosticsNode>[
ErrorSummary('RenderSliver geometry setter called incorrectly.'),
violation
violation,
if (hint != null) hint,
contract,
describeForError('The RenderSliver in question is'),
];
if (hint != null)
information.add(hint);
information.add(contract);
information.add(describeForError('The RenderSliver in question is'));
throw FlutterError.fromParts(information);
}());
_geometry = value;

View File

@ -213,19 +213,14 @@ class StackParentData extends ContainerBoxParentData<RenderBox> {
@override
String toString() {
final List<String> values = <String>[];
if (top != null)
values.add('top=${debugFormatDouble(top)}');
if (right != null)
values.add('right=${debugFormatDouble(right)}');
if (bottom != null)
values.add('bottom=${debugFormatDouble(bottom)}');
if (left != null)
values.add('left=${debugFormatDouble(left)}');
if (width != null)
values.add('width=${debugFormatDouble(width)}');
if (height != null)
values.add('height=${debugFormatDouble(height)}');
final List<String> values = <String>[
if (top != null) 'top=${debugFormatDouble(top)}',
if (right != null) 'right=${debugFormatDouble(right)}',
if (bottom != null) 'bottom=${debugFormatDouble(bottom)}',
if (left != null) 'left=${debugFormatDouble(left)}',
if (width != null) 'width=${debugFormatDouble(width)}',
if (height != null) 'height=${debugFormatDouble(height)}',
];
if (values.isEmpty)
values.add('not positioned');
values.add(super.toString());

View File

@ -363,22 +363,22 @@ class SemanticsData extends Diagnosticable {
properties.add(TransformProperty('transform', transform, showName: false, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0));
properties.add(DoubleProperty('thickness', thickness, defaultValue: 0.0));
final List<String> actionSummary = <String>[];
for (SemanticsAction action in SemanticsAction.values.values) {
if ((actions & action.index) != 0)
actionSummary.add(describeEnum(action));
}
final List<String> actionSummary = <String>[
for (SemanticsAction action in SemanticsAction.values.values)
if ((actions & action.index) != 0)
describeEnum(action),
];
final List<String> customSemanticsActionSummary = customSemanticsActionIds
.map<String>((int actionId) => CustomSemanticsAction.getAction(actionId).label)
.toList();
properties.add(IterableProperty<String>('actions', actionSummary, ifEmpty: null));
properties.add(IterableProperty<String>('customActions', customSemanticsActionSummary, ifEmpty: null));
final List<String> flagSummary = <String>[];
for (SemanticsFlag flag in SemanticsFlag.values.values) {
if ((flags & flag.index) != 0)
flagSummary.add(describeEnum(flag));
}
final List<String> flagSummary = <String>[
for (SemanticsFlag flag in SemanticsFlag.values.values)
if ((flags & flag.index) != 0)
describeEnum(flag),
];
properties.add(IterableProperty<String>('flags', flagSummary, ifEmpty: null));
properties.add(StringProperty('label', label, defaultValue: ''));
properties.add(StringProperty('value', value, defaultValue: ''));

View File

@ -206,12 +206,9 @@ class SystemUiOverlayStyle {
}
}
List<String> _stringify(List<dynamic> list) {
final List<String> result = <String>[];
for (dynamic item in list)
result.add(item.toString());
return result;
}
List<String> _stringify(List<dynamic> list) => <String>[
for (dynamic item in list) item.toString(),
];
/// Controls specific aspects of the operating system's graphical interface and
/// how it interacts with the application.

View File

@ -276,11 +276,11 @@ class AnimatedSwitcher extends StatefulWidget {
///
/// This is an [AnimatedSwitcherLayoutBuilder] function.
static Widget defaultLayoutBuilder(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.center,
);
}

View File

@ -5714,17 +5714,13 @@ class _PointerListener extends SingleChildRenderObjectWidget {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
final List<String> listeners = <String>[];
if (onPointerDown != null)
listeners.add('down');
if (onPointerMove != null)
listeners.add('move');
if (onPointerUp != null)
listeners.add('up');
if (onPointerCancel != null)
listeners.add('cancel');
if (onPointerSignal != null)
listeners.add('signal');
final List<String> listeners = <String>[
if (onPointerDown != null) 'down',
if (onPointerMove != null) 'move',
if (onPointerUp != null) 'up',
if (onPointerCancel != null) 'cancel',
if (onPointerSignal != null) 'signal',
];
properties.add(IterableProperty<String>('listeners', listeners, ifEmpty: '<none>'));
properties.add(EnumProperty<HitTestBehavior>('behavior', behavior));
}

View File

@ -549,22 +549,19 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
);
if (background != null) {
final List<Widget> children = <Widget>[];
if (!_moveAnimation.isDismissed) {
children.add(Positioned.fill(
child: ClipRect(
clipper: _DismissibleClipper(
axis: _directionIsXAxis ? Axis.horizontal : Axis.vertical,
moveAnimation: _moveAnimation,
content = Stack(children: <Widget>[
if (!_moveAnimation.isDismissed)
Positioned.fill(
child: ClipRect(
clipper: _DismissibleClipper(
axis: _directionIsXAxis ? Axis.horizontal : Axis.vertical,
moveAnimation: _moveAnimation,
),
child: background,
),
child: background,
),
));
}
children.add(content);
content = Stack(children: children);
content,
]);
}
// We are not resizing but we may be being dragging in widget.direction.
return GestureDetector(

View File

@ -657,10 +657,9 @@ class ReadingOrderTraversalPolicy extends FocusTraversalPolicy with DirectionalF
return topmost;
}
final List<_SortData> data = <_SortData>[];
for (FocusNode node in nodes) {
data.add(_SortData(node));
}
final List<_SortData> data = <_SortData>[
for (FocusNode node in nodes) _SortData(node),
];
// Pick the initial widget as the one that is leftmost in the band of the
// topmost, or the topmost, if there are no others in its band.

View File

@ -263,15 +263,14 @@ class FixedExtentScrollController extends ScrollController {
return;
}
final List<Future<void>> futures = <Future<void>>[];
for (_FixedExtentScrollPosition position in positions) {
futures.add(position.animateTo(
itemIndex * position.itemExtent,
duration: duration,
curve: curve,
));
}
await Future.wait<void>(futures);
await Future.wait<void>(<Future<void>>[
for (_FixedExtentScrollPosition position in positions)
position.animateTo(
itemIndex * position.itemExtent,
duration: duration,
curve: curve,
),
]);
}
/// Changes which item index is centered in the controlled scroll view.

View File

@ -61,17 +61,6 @@ class NavigationToolbar extends StatelessWidget {
@override
Widget build(BuildContext context) {
assert(debugCheckHasDirectionality(context));
final List<Widget> children = <Widget>[];
if (leading != null)
children.add(LayoutId(id: _ToolbarSlot.leading, child: leading));
if (middle != null)
children.add(LayoutId(id: _ToolbarSlot.middle, child: middle));
if (trailing != null)
children.add(LayoutId(id: _ToolbarSlot.trailing, child: trailing));
final TextDirection textDirection = Directionality.of(context);
return CustomMultiChildLayout(
delegate: _ToolbarLayout(
@ -79,7 +68,11 @@ class NavigationToolbar extends StatelessWidget {
middleSpacing: middleSpacing,
textDirection: textDirection,
),
children: children,
children: <Widget>[
if (leading != null) LayoutId(id: _ToolbarSlot.leading, child: leading),
if (middle != null) LayoutId(id: _ToolbarSlot.middle, child: middle),
if (trailing != null) LayoutId(id: _ToolbarSlot.trailing, child: trailing),
],
);
}
}

View File

@ -660,10 +660,9 @@ class _RenderTheatre extends RenderBox
@override
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
if (child != null)
children.add(child.toDiagnosticsNode(name: 'onstage'));
final List<DiagnosticsNode> children = <DiagnosticsNode>[
if (child != null) child.toDiagnosticsNode(name: 'onstage'),
];
if (firstChild != null) {
RenderBox child = firstChild;

View File

@ -589,11 +589,10 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
@override
void initState() {
super.initState();
final List<Listenable> animations = <Listenable>[];
if (widget.route.animation != null)
animations.add(widget.route.animation);
if (widget.route.secondaryAnimation != null)
animations.add(widget.route.secondaryAnimation);
final List<Listenable> animations = <Listenable>[
if (widget.route.animation != null) widget.route.animation,
if (widget.route.secondaryAnimation != null) widget.route.secondaryAnimation,
];
_listenable = Listenable.merge(animations);
if (widget.route.isCurrent) {
widget.route.navigator.focusScopeNode.setFirstFocus(focusScopeNode);

View File

@ -143,11 +143,10 @@ class SliverPersistentHeader extends StatelessWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<SliverPersistentHeaderDelegate>('delegate', delegate));
final List<String> flags = <String>[];
if (pinned)
flags.add('pinned');
if (floating)
flags.add('floating');
final List<String> flags = <String>[
if (pinned) 'pinned',
if (floating) 'floating',
];
if (flags.isEmpty)
flags.add('normal');
properties.add(IterableProperty<String>('mode', flags));

View File

@ -2267,30 +2267,29 @@ class _WidgetInspectorState extends State<WidgetInspector>
@override
Widget build(BuildContext context) {
final List<Widget> children = <Widget>[];
children.add(GestureDetector(
onTap: _handleTap,
onPanDown: _handlePanDown,
onPanEnd: _handlePanEnd,
onPanUpdate: _handlePanUpdate,
behavior: HitTestBehavior.opaque,
excludeFromSemantics: true,
child: IgnorePointer(
ignoring: isSelectMode,
key: _ignorePointerKey,
ignoringSemantics: false,
child: widget.child,
return Stack(children: <Widget>[
GestureDetector(
onTap: _handleTap,
onPanDown: _handlePanDown,
onPanEnd: _handlePanEnd,
onPanUpdate: _handlePanUpdate,
behavior: HitTestBehavior.opaque,
excludeFromSemantics: true,
child: IgnorePointer(
ignoring: isSelectMode,
key: _ignorePointerKey,
ignoringSemantics: false,
child: widget.child,
),
),
));
if (!isSelectMode && widget.selectButtonBuilder != null) {
children.add(Positioned(
left: _kInspectButtonMargin,
bottom: _kInspectButtonMargin,
child: widget.selectButtonBuilder(context, _handleEnableSelect),
));
}
children.add(_InspectorOverlay(selection: selection));
return Stack(children: children);
if (!isSelectMode && widget.selectButtonBuilder != null)
Positioned(
left: _kInspectButtonMargin,
bottom: _kInspectButtonMargin,
child: widget.selectButtonBuilder(context, _handleEnableSelect),
),
_InspectorOverlay(selection: selection),
]);
}
}

View File

@ -105,19 +105,19 @@ void main() {
});
List<double> estimateBounds(Curve curve) {
final List<double> values = <double>[];
values.add(curve.transform(0.0));
values.add(curve.transform(0.1));
values.add(curve.transform(0.2));
values.add(curve.transform(0.3));
values.add(curve.transform(0.4));
values.add(curve.transform(0.5));
values.add(curve.transform(0.6));
values.add(curve.transform(0.7));
values.add(curve.transform(0.8));
values.add(curve.transform(0.9));
values.add(curve.transform(1.0));
final List<double> values = <double>[
curve.transform(0.0),
curve.transform(0.1),
curve.transform(0.2),
curve.transform(0.3),
curve.transform(0.4),
curve.transform(0.5),
curve.transform(0.6),
curve.transform(0.7),
curve.transform(0.8),
curve.transform(0.9),
curve.transform(1.0),
];
return <double>[
values.reduce(math.min),

View File

@ -246,16 +246,13 @@ class TestTree extends Object with DiagnosticableTreeMixin {
final DiagnosticsTreeStyle style;
@override
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
for (TestTree child in this.children) {
children.add(child.toDiagnosticsNode(
List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[
for (TestTree child in children)
child.toDiagnosticsNode(
name: 'child ${child.name}',
style: child.style,
));
}
return children;
}
),
];
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {

View File

@ -22,16 +22,13 @@ class TestTree extends Object with DiagnosticableTreeMixin {
final DiagnosticsTreeStyle style;
@override
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
for (TestTree child in this.children) {
children.add(child.toDiagnosticsNode(
List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[
for (TestTree child in children)
child.toDiagnosticsNode(
name: 'child ${child.name}',
style: child.style,
));
}
return children;
}
),
];
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {

View File

@ -371,9 +371,9 @@ void main() {
testWidgets('Dropdown screen edges', (WidgetTester tester) async {
int value = 4;
final List<DropdownMenuItem<int>> items = <DropdownMenuItem<int>>[];
for (int i = 0; i < 20; ++i)
items.add(DropdownMenuItem<int>(value: i, child: Text('$i')));
final List<DropdownMenuItem<int>> items = <DropdownMenuItem<int>>[
for (int i = 0; i < 20; ++i) DropdownMenuItem<int>(value: i, child: Text('$i')),
];
void handleChanged(int newValue) {
value = newValue;

View File

@ -237,11 +237,11 @@ void main() {
});
test('Notifies listeners of chunk events', () async {
final List<Uint8List> chunks = <Uint8List>[];
const int chunkSize = 8;
for (int offset = 0; offset < kTransparentImage.length; offset += chunkSize) {
chunks.add(Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()));
}
final List<Uint8List> chunks = <Uint8List>[
for (int offset = 0; offset < kTransparentImage.length; offset += chunkSize)
Uint8List.fromList(kTransparentImage.skip(offset).take(chunkSize).toList()),
];
final Completer<void> imageAvailable = Completer<void>();
final MockHttpClientRequest request = MockHttpClientRequest();
final MockHttpClientResponse response = MockHttpClientResponse();

View File

@ -127,10 +127,11 @@ void main() {
// The list is currently in the wrong order (so selection boxes will paint in the wrong order).
);
final List<List<TextBox>> list = <List<TextBox>>[];
textSpan = painter.text;
for (int index = 0; index < textSpan.text.length; index += 1)
list.add(painter.getBoxesForSelection(TextSelection(baseOffset: index, extentOffset: index + 1)));
final List<List<TextBox>> list = <List<TextBox>>[
for (int index = 0; index < textSpan.text.length; index += 1)
painter.getBoxesForSelection(TextSelection(baseOffset: index, extentOffset: index + 1)),
];
expect(list, const <List<TextBox>>[
<TextBox>[], // U+202E, non-printing Unicode bidi formatting character
<TextBox>[TextBox.fromLTRBD(230.0, 0.0, 240.0, 10.0, TextDirection.rtl)],
@ -390,10 +391,11 @@ void main() {
skip: skipExpectsWithKnownBugs, // horizontal offsets are one pixel off in places; vertical offsets are good
);
final List<List<TextBox>> list = <List<TextBox>>[];
for (int index = 0; index < 5+4+5; index += 1)
list.add(painter.getBoxesForSelection(TextSelection(baseOffset: index, extentOffset: index + 1)));
print(list);
final List<List<TextBox>> list = <List<TextBox>>[
for (int index = 0; index < 5+4+5; index += 1)
painter.getBoxesForSelection(TextSelection(baseOffset: index, extentOffset: index + 1)),
];
expect(list, const <List<TextBox>>[
<TextBox>[TextBox.fromLTRBD(0.0, 8.0, 10.0, 18.0, TextDirection.ltr)],
<TextBox>[TextBox.fromLTRBD(10.0, 8.0, 20.0, 18.0, TextDirection.ltr)],

View File

@ -444,15 +444,14 @@ class _PathMatcher extends Matcher {
return false;
}
final Path path = object;
final List<String> errors = <String>[];
for (Offset offset in includes) {
if (!path.contains(offset))
errors.add('Offset $offset should be inside the path, but is not.');
}
for (Offset offset in excludes) {
if (path.contains(offset))
errors.add('Offset $offset should be outside the path, but is not.');
}
final List<String> errors = <String>[
for (Offset offset in includes)
if (!path.contains(offset))
'Offset $offset should be inside the path, but is not.',
for (Offset offset in excludes)
if (path.contains(offset))
'Offset $offset should be outside the path, but is not.',
];
if (errors.isEmpty)
return true;
matchState[this] = 'Not all the given points were inside or outside the path as expected:\n ${errors.join("\n ")}';
@ -1458,9 +1457,10 @@ class _FunctionPaintPredicate extends _PaintPredicate {
@override
String toString() {
final List<String> adjectives = <String>[];
for (int index = 0; index < arguments.length; index += 1)
adjectives.add(arguments[index] != null ? _valueName(arguments[index]) : '...');
final List<String> adjectives = <String>[
for (int index = 0; index < arguments.length; index += 1)
arguments[index] != null ? _valueName(arguments[index]) : '...',
];
return '${_symbolName(symbol)}(${adjectives.join(", ")})';
}
}

View File

@ -338,10 +338,11 @@ void main() {
);
// Fake the render boxes that correspond to the WidgetSpans. We use
// RenderParagraph to reduce dependencies this test has.
final List<RenderBox> renderBoxes = <RenderBox>[];
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
final List<RenderBox> renderBoxes = <RenderBox>[
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
];
final RenderParagraph paragraph = RenderParagraph(
text,
@ -380,14 +381,15 @@ void main() {
);
// Fake the render boxes that correspond to the WidgetSpans. We use
// RenderParagraph to reduce dependencies this test has.
final List<RenderBox> renderBoxes = <RenderBox>[];
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
final List<RenderBox> renderBoxes = <RenderBox>[
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr),
];
final RenderParagraph paragraph = RenderParagraph(
text,

View File

@ -263,10 +263,9 @@ void main() {
];
final List<int> expectedResults = <int>[0, -1, 1, 0];
assert(tests.length == expectedResults.length);
final List<int> results = <int>[];
for (List<SemanticsSortKey> tuple in tests) {
results.add(tuple[0].compareTo(tuple[1]));
}
final List<int> results = <int>[
for (List<SemanticsSortKey> tuple in tests) tuple[0].compareTo(tuple[1]),
];
expect(results, orderedEquals(expectedResults));
});
@ -279,10 +278,9 @@ void main() {
];
final List<int> expectedResults = <int>[0, -1, 1, 0];
assert(tests.length == expectedResults.length);
final List<int> results = <int>[];
for (List<SemanticsSortKey> tuple in tests) {
results.add(tuple[0].compareTo(tuple[1]));
}
final List<int> results = <int>[
for (List<SemanticsSortKey> tuple in tests) tuple[0].compareTo(tuple[1]),
];
expect(results, orderedEquals(expectedResults));
});

View File

@ -708,21 +708,17 @@ class _DiffTester {
final SemanticsTester semanticsTester = SemanticsTester(tester);
TestSemantics createExpectations(List<String> labels) {
final List<TestSemantics> children = <TestSemantics>[];
for (String label in labels) {
children.add(
TestSemantics(
rect: const Rect.fromLTRB(1.0, 1.0, 2.0, 2.0),
label: label,
),
);
}
return TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
rect: TestSemantics.fullScreen,
children: children,
children: <TestSemantics>[
for (String label in labels)
TestSemantics(
rect: const Rect.fromLTRB(1.0, 1.0, 2.0, 2.0),
label: label,
),
],
),
],
);

View File

@ -29,17 +29,17 @@ class OrderSwitcherState extends State<OrderSwitcher> {
@override
Widget build(BuildContext context) {
final List<Widget> children = <Widget>[];
if (_aFirst) {
children.add(KeyedSubtree(child: widget.a));
children.add(widget.b);
} else {
children.add(KeyedSubtree(child: widget.b));
children.add(widget.a);
}
return Stack(
textDirection: TextDirection.ltr,
children: children,
children: _aFirst
? <Widget>[
KeyedSubtree(child: widget.a),
widget.b,
]
: <Widget>[
KeyedSubtree(child: widget.b),
widget.a
],
);
}
}

View File

@ -8,15 +8,12 @@ import 'package:flutter/widgets.dart';
void main() {
testWidgets('Does not animate if already at target position', (WidgetTester tester) async {
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 80; i++)
textWidgets.add(Text('$i', textDirection: TextDirection.ltr));
final ScrollController controller = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: ListView(
children: textWidgets,
children: List<Widget>.generate(80, (int i) => Text('$i', textDirection: TextDirection.ltr)),
controller: controller,
),
),
@ -31,15 +28,12 @@ void main() {
});
testWidgets('Does not animate if already at target position within tolerance', (WidgetTester tester) async {
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 80; i++)
textWidgets.add(Text('$i', textDirection: TextDirection.ltr));
final ScrollController controller = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: ListView(
children: textWidgets,
children: List<Widget>.generate(80, (int i) => Text('$i', textDirection: TextDirection.ltr)),
controller: controller,
),
),
@ -57,15 +51,12 @@ void main() {
});
testWidgets('Animates if going to a position outside of tolerance', (WidgetTester tester) async {
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 80; i++)
textWidgets.add(Text('$i', textDirection: TextDirection.ltr));
final ScrollController controller = ScrollController();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: ListView(
children: textWidgets,
children: List<Widget>.generate(80, (int i) => Text('$i', textDirection: TextDirection.ltr)),
controller: controller,
),
),

View File

@ -11,14 +11,11 @@ import 'test_widgets.dart';
void main() {
testWidgets('simultaneously dispose a widget and end the scroll animation', (WidgetTester tester) async {
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 250; i++)
textWidgets.add(Text('$i'));
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: FlipWidget(
left: ListView(children: textWidgets),
left: ListView(children: List<Widget>.generate(250, (int i) => Text('$i'))),
right: Container(),
),
),

View File

@ -59,14 +59,16 @@ void main() {
testWidgets('fling and tap to stop', (WidgetTester tester) async {
final List<String> log = <String>[];
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 250; i += 1)
textWidgets.add(GestureDetector(onTap: () { log.add('tap $i'); }, child: Text('$i', style: testFont)));
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: ListView(children: textWidgets, dragStartBehavior: DragStartBehavior.down),
child: ListView(
dragStartBehavior: DragStartBehavior.down,
children: List<Widget>.generate(250, (int i) => GestureDetector(
onTap: () { log.add('tap $i'); },
child: Text('$i', style: testFont),
)),
),
),
);
@ -87,14 +89,16 @@ void main() {
testWidgets('fling and wait and tap', (WidgetTester tester) async {
final List<String> log = <String>[];
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 250; i += 1)
textWidgets.add(GestureDetector(onTap: () { log.add('tap $i'); }, child: Text('$i', style: testFont)));
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: ListView(children: textWidgets, dragStartBehavior: DragStartBehavior.down),
child: ListView(
dragStartBehavior: DragStartBehavior.down,
children: List<Widget>.generate(250, (int i) => GestureDetector(
onTap: () { log.add('tap $i'); },
child: Text('$i', style: testFont),
)),
),
),
);

View File

@ -21,14 +21,10 @@ void main() {
testWidgets('scrollable exposes the correct semantic actions', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 80; i++)
textWidgets.add(Text('$i'));
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: ListView(children: textWidgets),
child: ListView(children: List<Widget>.generate(80, (int i) => Text('$i'))),
),
);
@ -54,12 +50,12 @@ void main() {
const double kItemHeight = 40.0;
final List<Widget> containers = <Widget>[];
for (int i = 0; i < 80; i++)
containers.add(MergeSemantics(child: Container(
final List<Widget> containers = List<Widget>.generate(80, (int i) => MergeSemantics(
child: Container(
height: kItemHeight,
child: Text('container $i', textDirection: TextDirection.ltr),
)));
),
));
final ScrollController scrollController = ScrollController(
initialScrollOffset: kItemHeight / 2,
@ -93,12 +89,12 @@ void main() {
const double kItemHeight = 100.0;
const double kExpandedAppBarHeight = 56.0;
final List<Widget> containers = <Widget>[];
for (int i = 0; i < 80; i++)
containers.add(MergeSemantics(child: Container(
final List<Widget> containers = List<Widget>.generate(80, (int i) => MergeSemantics(
child: Container(
height: kItemHeight,
child: Text('container $i'),
)));
),
));
final ScrollController scrollController = ScrollController(
initialScrollOffset: kItemHeight / 2,
@ -219,12 +215,9 @@ void main() {
testWidgets('correct scrollProgress', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 80; i++)
textWidgets.add(Text('$i'));
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ListView(children: textWidgets),
child: ListView(children: List<Widget>.generate(80, (int i) => Text('$i'))),
));
expect(semantics, includesNodeWith(
@ -315,12 +308,10 @@ void main() {
testWidgets('Semantics tree is populated mid-scroll', (WidgetTester tester) async {
semantics = SemanticsTester(tester);
final List<Widget> children = <Widget>[];
for (int i = 0; i < 80; i++)
children.add(Container(
child: Text('Item $i'),
height: 40.0,
));
final List<Widget> children = List<Widget>.generate(80, (int i) => Container(
child: Text('Item $i'),
height: 40.0,
));
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,

View File

@ -751,25 +751,17 @@ class _IncludesNodeWith extends Matcher {
}
String get _configAsString {
final List<String> strings = <String>[];
if (label != null)
strings.add('label "$label"');
if (value != null)
strings.add('value "$value"');
if (hint != null)
strings.add('hint "$hint"');
if (textDirection != null)
strings.add(' (${describeEnum(textDirection)})');
if (actions != null)
strings.add('actions "${actions.join(', ')}"');
if (flags != null)
strings.add('flags "${flags.join(', ')}"');
if (scrollPosition != null)
strings.add('scrollPosition "$scrollPosition"');
if (scrollExtentMax != null)
strings.add('scrollExtentMax "$scrollExtentMax"');
if (scrollExtentMin != null)
strings.add('scrollExtentMin "$scrollExtentMin"');
final List<String> strings = <String>[
if (label != null) 'label "$label"',
if (value != null) 'value "$value"',
if (hint != null) 'hint "$hint"',
if (textDirection != null) ' (${describeEnum(textDirection)})',
if (actions != null) 'actions "${actions.join(', ')}"',
if (flags != null) 'flags "${flags.join(', ')}"',
if (scrollPosition != null) 'scrollPosition "$scrollPosition"',
if (scrollExtentMax != null) 'scrollExtentMax "$scrollExtentMax"',
if (scrollExtentMin != null) 'scrollExtentMin "$scrollExtentMin"',
];
return strings.join(', ');
}
}

View File

@ -1123,12 +1123,11 @@ void _unhandledJsonRpcError(dynamic error, dynamic stack) {
String _getWebSocketUrl(String url) {
Uri uri = Uri.parse(url);
final List<String> pathSegments = <String>[];
// If there's an authentication code (default), we need to add it to our path.
if (uri.pathSegments.isNotEmpty) {
pathSegments.add(uri.pathSegments.first);
}
pathSegments.add('ws');
final List<String> pathSegments = <String>[
// If there's an authentication code (default), we need to add it to our path.
if (uri.pathSegments.isNotEmpty) uri.pathSegments.first,
'ws',
];
if (uri.scheme == 'http')
uri = uri.replace(scheme: 'ws', pathSegments: pathSegments);
return uri.toString();

View File

@ -5,7 +5,7 @@ author: Flutter Authors <flutter-dev@googlegroups.com>
environment:
# The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.2.2 <3.0.0"
dependencies:
file: 5.0.10

View File

@ -482,93 +482,53 @@ Matcher matchesSemantics({
List<CustomSemanticsAction> customActions,
List<Matcher> children,
}) {
final List<SemanticsFlag> flags = <SemanticsFlag>[];
if (hasCheckedState)
flags.add(SemanticsFlag.hasCheckedState);
if (isChecked)
flags.add(SemanticsFlag.isChecked);
if (isSelected)
flags.add(SemanticsFlag.isSelected);
if (isButton)
flags.add(SemanticsFlag.isButton);
if (isTextField)
flags.add(SemanticsFlag.isTextField);
if (isReadOnly)
flags.add(SemanticsFlag.isReadOnly);
if (isFocused)
flags.add(SemanticsFlag.isFocused);
if (hasEnabledState)
flags.add(SemanticsFlag.hasEnabledState);
if (isEnabled)
flags.add(SemanticsFlag.isEnabled);
if (isInMutuallyExclusiveGroup)
flags.add(SemanticsFlag.isInMutuallyExclusiveGroup);
if (isHeader)
flags.add(SemanticsFlag.isHeader);
if (isObscured)
flags.add(SemanticsFlag.isObscured);
if (isMultiline)
flags.add(SemanticsFlag.isMultiline);
if (namesRoute)
flags.add(SemanticsFlag.namesRoute);
if (scopesRoute)
flags.add(SemanticsFlag.scopesRoute);
if (isHidden)
flags.add(SemanticsFlag.isHidden);
if (isImage)
flags.add(SemanticsFlag.isImage);
if (isLiveRegion)
flags.add(SemanticsFlag.isLiveRegion);
if (hasToggledState)
flags.add(SemanticsFlag.hasToggledState);
if (isToggled)
flags.add(SemanticsFlag.isToggled);
if (hasImplicitScrolling)
flags.add(SemanticsFlag.hasImplicitScrolling);
final List<SemanticsFlag> flags = <SemanticsFlag>[
if (hasCheckedState) SemanticsFlag.hasCheckedState,
if (isChecked) SemanticsFlag.isChecked,
if (isSelected) SemanticsFlag.isSelected,
if (isButton) SemanticsFlag.isButton,
if (isTextField) SemanticsFlag.isTextField,
if (isReadOnly) SemanticsFlag.isReadOnly,
if (isFocused) SemanticsFlag.isFocused,
if (hasEnabledState) SemanticsFlag.hasEnabledState,
if (isEnabled) SemanticsFlag.isEnabled,
if (isInMutuallyExclusiveGroup) SemanticsFlag.isInMutuallyExclusiveGroup,
if (isHeader) SemanticsFlag.isHeader,
if (isObscured) SemanticsFlag.isObscured,
if (isMultiline) SemanticsFlag.isMultiline,
if (namesRoute) SemanticsFlag.namesRoute,
if (scopesRoute) SemanticsFlag.scopesRoute,
if (isHidden) SemanticsFlag.isHidden,
if (isImage) SemanticsFlag.isImage,
if (isLiveRegion) SemanticsFlag.isLiveRegion,
if (hasToggledState) SemanticsFlag.hasToggledState,
if (isToggled) SemanticsFlag.isToggled,
if (hasImplicitScrolling) SemanticsFlag.hasImplicitScrolling,
];
final List<SemanticsAction> actions = <SemanticsAction>[];
if (hasTapAction)
actions.add(SemanticsAction.tap);
if (hasLongPressAction)
actions.add(SemanticsAction.longPress);
if (hasScrollLeftAction)
actions.add(SemanticsAction.scrollLeft);
if (hasScrollRightAction)
actions.add(SemanticsAction.scrollRight);
if (hasScrollUpAction)
actions.add(SemanticsAction.scrollUp);
if (hasScrollDownAction)
actions.add(SemanticsAction.scrollDown);
if (hasIncreaseAction)
actions.add(SemanticsAction.increase);
if (hasDecreaseAction)
actions.add(SemanticsAction.decrease);
if (hasShowOnScreenAction)
actions.add(SemanticsAction.showOnScreen);
if (hasMoveCursorForwardByCharacterAction)
actions.add(SemanticsAction.moveCursorForwardByCharacter);
if (hasMoveCursorBackwardByCharacterAction)
actions.add(SemanticsAction.moveCursorBackwardByCharacter);
if (hasSetSelectionAction)
actions.add(SemanticsAction.setSelection);
if (hasCopyAction)
actions.add(SemanticsAction.copy);
if (hasCutAction)
actions.add(SemanticsAction.cut);
if (hasPasteAction)
actions.add(SemanticsAction.paste);
if (hasDidGainAccessibilityFocusAction)
actions.add(SemanticsAction.didGainAccessibilityFocus);
if (hasDidLoseAccessibilityFocusAction)
actions.add(SemanticsAction.didLoseAccessibilityFocus);
if (customActions != null && customActions.isNotEmpty)
actions.add(SemanticsAction.customAction);
if (hasDismissAction)
actions.add(SemanticsAction.dismiss);
if (hasMoveCursorForwardByWordAction)
actions.add(SemanticsAction.moveCursorForwardByWord);
if (hasMoveCursorBackwardByWordAction)
actions.add(SemanticsAction.moveCursorBackwardByWord);
final List<SemanticsAction> actions = <SemanticsAction>[
if (hasTapAction) SemanticsAction.tap,
if (hasLongPressAction) SemanticsAction.longPress,
if (hasScrollLeftAction) SemanticsAction.scrollLeft,
if (hasScrollRightAction) SemanticsAction.scrollRight,
if (hasScrollUpAction) SemanticsAction.scrollUp,
if (hasScrollDownAction) SemanticsAction.scrollDown,
if (hasIncreaseAction) SemanticsAction.increase,
if (hasDecreaseAction) SemanticsAction.decrease,
if (hasShowOnScreenAction) SemanticsAction.showOnScreen,
if (hasMoveCursorForwardByCharacterAction) SemanticsAction.moveCursorForwardByCharacter,
if (hasMoveCursorBackwardByCharacterAction) SemanticsAction.moveCursorBackwardByCharacter,
if (hasSetSelectionAction) SemanticsAction.setSelection,
if (hasCopyAction) SemanticsAction.copy,
if (hasCutAction) SemanticsAction.cut,
if (hasPasteAction) SemanticsAction.paste,
if (hasDidGainAccessibilityFocusAction) SemanticsAction.didGainAccessibilityFocus,
if (hasDidLoseAccessibilityFocusAction) SemanticsAction.didLoseAccessibilityFocus,
if (customActions != null && customActions.isNotEmpty) SemanticsAction.customAction,
if (hasDismissAction) SemanticsAction.dismiss,
if (hasMoveCursorForwardByWordAction) SemanticsAction.moveCursorForwardByWord,
if (hasMoveCursorBackwardByWordAction) SemanticsAction.moveCursorBackwardByWord,
];
SemanticsHintOverrides hintOverrides;
if (onTapHint != null || onLongPressHint != null)
hintOverrides = SemanticsHintOverrides(
@ -1883,11 +1843,11 @@ class _MatchesSemanticsData extends Matcher {
for (SemanticsAction action in actions)
actionBits |= action.index;
if (actionBits != data.actions) {
final List<String> actionSummary = <String>[];
for (SemanticsAction action in SemanticsAction.values.values) {
if ((data.actions & action.index) != 0)
actionSummary.add(describeEnum(action));
}
final List<String> actionSummary = <String>[
for (SemanticsAction action in SemanticsAction.values.values)
if ((data.actions & action.index) != 0)
describeEnum(action),
];
return failWithDescription(matchState, 'actions were: $actionSummary');
}
}
@ -1917,11 +1877,11 @@ class _MatchesSemanticsData extends Matcher {
for (SemanticsFlag flag in flags)
flagBits |= flag.index;
if (flagBits != data.flags) {
final List<String> flagSummary = <String>[];
for (SemanticsFlag flag in SemanticsFlag.values.values) {
if ((data.flags & flag.index) != 0)
flagSummary.add(describeEnum(flag));
}
final List<String> flagSummary = <String>[
for (SemanticsFlag flag in SemanticsFlag.values.values)
if ((data.flags & flag.index) != 0)
describeEnum(flag),
];
return failWithDescription(matchState, 'flags were: $flagSummary');
}
}

View File

@ -185,9 +185,10 @@ class TestAsyncUtils {
assert(candidateScope.zone != null);
} while (candidateScope.zone != zone);
assert(scope != null);
final List<DiagnosticsNode> information = <DiagnosticsNode>[];
information.add(ErrorSummary('Guarded function conflict.'));
information.add(ErrorHint('You must use "await" with all Future-returning test APIs.'));
final List<DiagnosticsNode> information = <DiagnosticsNode>[
ErrorSummary('Guarded function conflict.'),
ErrorHint('You must use "await" with all Future-returning test APIs.'),
];
final _StackEntry originalGuarder = _findResponsibleMethod(scope.creationStack, 'guard', information);
final _StackEntry collidingGuarder = _findResponsibleMethod(StackTrace.current, 'guardSync', information);
if (originalGuarder != null && collidingGuarder != null) {

View File

@ -73,11 +73,10 @@ String getAvdPath() {
final List<String> searchPaths = <String>[
platform.environment['ANDROID_AVD_HOME'],
if (platform.environment['HOME'] != null)
fs.path.join(platform.environment['HOME'], '.android', 'avd'),
];
if (platform.environment['HOME'] != null) {
searchPaths.add(fs.path.join(platform.environment['HOME'], '.android', 'avd'));
}
if (platform.isWindows) {
final String homeDrive = platform.environment['HOMEDRIVE'];

View File

@ -236,13 +236,13 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
// flavors and build types defined in the project. If gradle fails, then check if the failure is due to t
try {
final RunResult propertiesRunResult = await processUtils.run(
<String>[gradlew, isLibrary ? 'properties' : 'app:properties'],
<String>[gradlew, if (isLibrary) 'properties' else 'app:properties'],
throwOnError: true,
workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv,
);
final RunResult tasksRunResult = await processUtils.run(
<String>[gradlew, isLibrary ? 'tasks': 'app:tasks', '--all', '--console=auto'],
<String>[gradlew, if (isLibrary) 'tasks' else 'app:tasks', '--all', '--console=auto'],
throwOnError: true,
workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv,

View File

@ -418,11 +418,10 @@ DevFSContent _createAssetManifest(Map<_Asset, List<_Asset>> assetVariants) {
..sort(_byBasename);
for (_Asset main in sortedKeys) {
final List<String> variants = <String>[];
for (_Asset variant in assetVariants[main]) {
variants.add(variant.entryUri.path);
}
jsonObject[main.entryUri.path] = variants;
jsonObject[main.entryUri.path] = <String>[
for (_Asset variant in assetVariants[main])
variant.entryUri.path,
];
}
return DevFSStringContent(json.encode(jsonObject));
}

View File

@ -142,11 +142,11 @@ class _PosixUtils extends OperatingSystemUtils {
@override
List<File> _which(String execName, { bool all = false }) {
final List<String> command = <String>['which'];
if (all) {
command.add('-a');
}
command.add(execName);
final List<String> command = <String>[
'which',
if (all) '-a',
execName,
];
final ProcessResult result = processManager.runSync(command);
if (result.exitCode != 0) {
return const <File>[];

Some files were not shown because too many files have changed in this diff Show More