@@ -289,38 +289,49 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
289
289
}
290
290
291
291
void performLayout () {
292
- // Based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexible Lengths
293
- // Steps 1-3. Determine used flex factor, size inflexible items, calculate free space
292
+ // Originally based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexible Lengths
293
+
294
+ // Determine used flex factor, size inflexible items, calculate free space.
294
295
int totalFlex = 0 ;
295
296
int totalChildren = 0 ;
296
297
assert (constraints != null );
297
298
final double mainSize = (_direction == FlexDirection .horizontal) ? constraints.maxWidth : constraints.maxHeight;
298
- double crossSize = 0.0 ; // This will be determined after laying out the children
299
- double freeSpace = mainSize;
299
+ final bool canFlex = mainSize < double .INFINITY ;
300
+ double crossSize = 0.0 ; // This is determined as we lay out the children
301
+ double freeSpace = canFlex ? mainSize : 0.0 ;
300
302
RenderBox child = firstChild;
301
303
while (child != null ) {
302
304
assert (child.parentData is FlexBoxParentData );
303
305
totalChildren++ ;
304
306
int flex = _getFlex (child);
305
307
if (flex > 0 ) {
308
+ // Flexible children can only be used when the RenderFlex box's container has a finite size.
309
+ // When the container is infinite, for example if you are in a scrollable viewport, then
310
+ // it wouldn't make any sense to have a flexible child.
311
+ assert (canFlex && 'See https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/widgets/flex.md' is String );
306
312
totalFlex += child.parentData.flex;
307
313
} else {
308
314
BoxConstraints innerConstraints;
309
315
if (alignItems == FlexAlignItems .stretch) {
310
316
switch (_direction) {
311
317
case FlexDirection .horizontal:
312
- innerConstraints = new BoxConstraints (maxWidth: constraints.maxWidth,
313
- minHeight: constraints.minHeight,
318
+ innerConstraints = new BoxConstraints (minHeight: constraints.minHeight,
314
319
maxHeight: constraints.maxHeight);
315
320
break ;
316
321
case FlexDirection .vertical:
317
322
innerConstraints = new BoxConstraints (minWidth: constraints.minWidth,
318
- maxWidth: constraints.maxWidth,
319
- maxHeight: constraints.maxHeight);
323
+ maxWidth: constraints.maxWidth);
320
324
break ;
321
325
}
322
326
} else {
323
- innerConstraints = constraints.loosen ();
327
+ switch (_direction) {
328
+ case FlexDirection .horizontal:
329
+ innerConstraints = new BoxConstraints (maxHeight: constraints.maxHeight);
330
+ break ;
331
+ case FlexDirection .vertical:
332
+ innerConstraints = new BoxConstraints (maxWidth: constraints.maxWidth);
333
+ break ;
334
+ }
324
335
}
325
336
child.layout (innerConstraints, parentUsesSize: true );
326
337
freeSpace -= _getMainSize (child);
@@ -331,63 +342,98 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
331
342
_overflow = math.max (0.0 , - freeSpace);
332
343
freeSpace = math.max (0.0 , freeSpace);
333
344
334
- // Steps 4-5. Distribute remaining space to flexible children.
335
- double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0 ;
336
- double usedSpace = 0.0 ;
345
+ // Distribute remaining space to flexible children, and determine baseline.
337
346
double maxBaselineDistance = 0.0 ;
338
- child = firstChild;
339
- while (child != null ) {
340
- int flex = _getFlex (child);
341
- if (flex > 0 ) {
342
- double spaceForChild = spacePerFlex * flex;
343
- BoxConstraints innerConstraints;
344
- if (alignItems == FlexAlignItems .stretch) {
345
- switch (_direction) {
346
- case FlexDirection .horizontal:
347
- innerConstraints = new BoxConstraints (minWidth: spaceForChild,
348
- maxWidth: spaceForChild,
349
- minHeight: constraints.maxHeight,
350
- maxHeight: constraints.maxHeight);
351
- break ;
352
- case FlexDirection .vertical:
353
- innerConstraints = new BoxConstraints (minWidth: constraints.maxWidth,
354
- maxWidth: constraints.maxWidth,
355
- minHeight: spaceForChild,
356
- maxHeight: spaceForChild);
357
- break ;
358
- }
359
- } else {
360
- switch (_direction) {
361
- case FlexDirection .horizontal:
362
- innerConstraints = new BoxConstraints (minWidth: spaceForChild,
363
- maxWidth: spaceForChild,
364
- maxHeight: constraints.maxHeight);
365
- break ;
366
- case FlexDirection .vertical:
367
- innerConstraints = new BoxConstraints (maxWidth: constraints.maxWidth,
368
- minHeight: spaceForChild,
369
- maxHeight: spaceForChild);
370
- break ;
347
+ double usedSpace = 0.0 ;
348
+ if (totalFlex > 0 || alignItems == FlexAlignItems .baseline) {
349
+ double spacePerFlex = totalFlex > 0 ? (freeSpace / totalFlex) : 0.0 ;
350
+ child = firstChild;
351
+ while (child != null ) {
352
+ int flex = _getFlex (child);
353
+ if (flex > 0 ) {
354
+ double spaceForChild = spacePerFlex * flex;
355
+ BoxConstraints innerConstraints;
356
+ if (alignItems == FlexAlignItems .stretch) {
357
+ switch (_direction) {
358
+ case FlexDirection .horizontal:
359
+ innerConstraints = new BoxConstraints (minWidth: spaceForChild,
360
+ maxWidth: spaceForChild,
361
+ minHeight: constraints.maxHeight,
362
+ maxHeight: constraints.maxHeight);
363
+ break ;
364
+ case FlexDirection .vertical:
365
+ innerConstraints = new BoxConstraints (minWidth: constraints.maxWidth,
366
+ maxWidth: constraints.maxWidth,
367
+ minHeight: spaceForChild,
368
+ maxHeight: spaceForChild);
369
+ break ;
370
+ }
371
+ } else {
372
+ switch (_direction) {
373
+ case FlexDirection .horizontal:
374
+ innerConstraints = new BoxConstraints (minWidth: spaceForChild,
375
+ maxWidth: spaceForChild,
376
+ maxHeight: constraints.maxHeight);
377
+ break ;
378
+ case FlexDirection .vertical:
379
+ innerConstraints = new BoxConstraints (maxWidth: constraints.maxWidth,
380
+ minHeight: spaceForChild,
381
+ maxHeight: spaceForChild);
382
+ break ;
383
+ }
371
384
}
385
+ child.layout (innerConstraints, parentUsesSize: true );
386
+ usedSpace += _getMainSize (child);
387
+ crossSize = math.max (crossSize, _getCrossSize (child));
372
388
}
373
- child.layout (innerConstraints, parentUsesSize: true );
374
- usedSpace += _getMainSize (child);
375
- crossSize = math.max (crossSize, _getCrossSize (child));
376
- }
377
- if (alignItems == FlexAlignItems .baseline) {
378
- assert (textBaseline != null );
379
- double distance = child.getDistanceToBaseline (textBaseline, onlyReal: true );
380
- if (distance != null )
381
- maxBaselineDistance = math.max (maxBaselineDistance, distance);
389
+ if (alignItems == FlexAlignItems .baseline) {
390
+ assert (textBaseline != null );
391
+ double distance = child.getDistanceToBaseline (textBaseline, onlyReal: true );
392
+ if (distance != null )
393
+ maxBaselineDistance = math.max (maxBaselineDistance, distance);
394
+ }
395
+ assert (child.parentData is FlexBoxParentData );
396
+ child = child.parentData.nextSibling;
382
397
}
383
- assert (child.parentData is FlexBoxParentData );
384
- child = child.parentData.nextSibling;
385
398
}
386
399
387
- // Section 8.2: Main Axis Alignment using the justify-content property
388
- double remainingSpace = math.max (0.0 , freeSpace - usedSpace);
400
+ // Align items along the main axis.
389
401
double leadingSpace;
390
402
double betweenSpace;
403
+ double remainingSpace;
404
+ if (canFlex) {
405
+ remainingSpace = math.max (0.0 , freeSpace - usedSpace);
406
+ switch (_direction) {
407
+ case FlexDirection .horizontal:
408
+ size = constraints.constrain (new Size (mainSize, crossSize));
409
+ crossSize = size.height;
410
+ assert (size.width == mainSize);
411
+ break ;
412
+ case FlexDirection .vertical:
413
+ size = constraints.constrain (new Size (crossSize, mainSize));
414
+ crossSize = size.width;
415
+ assert (size.height == mainSize);
416
+ break ;
417
+ }
418
+ } else {
419
+ leadingSpace = 0.0 ;
420
+ betweenSpace = 0.0 ;
421
+ switch (_direction) {
422
+ case FlexDirection .horizontal:
423
+ size = constraints.constrain (new Size (- _overflow, crossSize));
424
+ crossSize = size.height;
425
+ assert (size.width >= - _overflow);
426
+ remainingSpace = size.width - - _overflow;
427
+ break ;
428
+ case FlexDirection .vertical:
429
+ size = constraints.constrain (new Size (crossSize, - _overflow));
430
+ crossSize = size.width;
431
+ assert (size.height >= - _overflow);
432
+ remainingSpace = size.height - - _overflow;
433
+ break ;
434
+ }
435
+ _overflow = 0.0 ;
436
+ }
391
437
switch (_justifyContent) {
392
438
case FlexJustifyContent .start:
393
439
leadingSpace = 0.0 ;
@@ -411,17 +457,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
411
457
break ;
412
458
}
413
459
414
- switch (_direction) {
415
- case FlexDirection .horizontal:
416
- size = constraints.constrain (new Size (mainSize, crossSize));
417
- crossSize = size.height;
418
- break ;
419
- case FlexDirection .vertical:
420
- size = constraints.constrain (new Size (crossSize, mainSize));
421
- crossSize = size.width;
422
- break ;
423
- }
424
-
425
460
// Position elements
426
461
double childMainPosition = leadingSpace;
427
462
child = firstChild;
@@ -517,4 +552,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
517
552
return header;
518
553
}
519
554
555
+ String debugDescribeSettings (String prefix) => '${super .debugDescribeSettings (prefix )}${prefix }direction: ${_direction }\n ${prefix }justifyContent: ${_justifyContent }\n ${prefix }alignItems: ${_alignItems }\n ${prefix }textBaseline: ${_textBaseline }\n ' ;
556
+
520
557
}
0 commit comments