Skip to content

Commit e7d5c7d

Browse files
authored
Change 'body' to be loosely constrained. (flutter#6692)
People get confused by the tight constraints.
1 parent 20063c5 commit e7d5c7d

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

packages/flutter/lib/src/material/scaffold.dart

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
7979

8080
// This part of the layout has the same effect as putting the app bar and
8181
// body in a column and making the body flexible. What's different is that
82-
// in this case the app bar appears -after- the body in the stacking order,
82+
// in this case the app bar appears _after_ the body in the stacking order,
8383
// so the app bar's shadow is drawn on top of the body.
8484

8585
final BoxConstraints fullWidthConstraints = looseConstraints.tighten(width: size.width);
@@ -108,7 +108,10 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
108108

109109
if (hasChild(_ScaffoldSlot.body)) {
110110
final double bodyHeight = contentBottom - contentTop;
111-
final BoxConstraints bodyConstraints = fullWidthConstraints.tighten(height: bodyHeight);
111+
final BoxConstraints bodyConstraints = new BoxConstraints(
112+
maxWidth: fullWidthConstraints.maxWidth,
113+
maxHeight: bodyHeight,
114+
);
112115
layoutChild(_ScaffoldSlot.body, bodyConstraints);
113116
positionChild(_ScaffoldSlot.body, new Offset(0.0, contentTop));
114117
}
@@ -325,22 +328,20 @@ class Scaffold extends StatefulWidget {
325328
/// [drawer]. To avoid the body being resized to avoid the window padding
326329
/// (e.g., from the onscreen keyboard), see [resizeToAvoidBottomPadding].
327330
///
328-
/// The widget in the body of the scaffold will be forced to the size of the
329-
/// available space, to cover the entire scaffold other than any app bars,
330-
/// footer buttons, or navigation bars.
331-
///
332-
/// To center this widget instead, consider putting it in a [Center] widget
333-
/// and having that be the body.
331+
/// The widget in the body of the scaffold is positioned at the top-left of
332+
/// the available space between the app bar and the bottom of the scaffold. To
333+
/// center this widget instead, consider putting it in a [Center] widget and
334+
/// having that be the body.
334335
///
335336
/// If you have a column of widgets that should normally fit on the screen,
336337
/// but may overflow and would in such cases need to scroll, consider using a
337338
/// [Block] as the body of the scaffold.
338339
///
339-
/// If you have a list of items, consider using a [LazyBlock] or
340-
/// [LazyScrollableList] as the body of the scaffold.
340+
/// If you have a list of items, consider using a [LazyBlock],
341+
/// [LazyScrollableList], or [MaterialList] as the body of the scaffold.
341342
final Widget body;
342343

343-
/// A button displayed on top of the body.
344+
/// A button displayed on top of the [body].
344345
///
345346
/// Typically a [FloatingActionButton].
346347
final Widget floatingActionButton;
@@ -357,7 +358,7 @@ class Scaffold extends StatefulWidget {
357358
/// * <https://material.google.com/components/buttons.html#buttons-persistent-footer-buttons>
358359
final List<Widget> persistentFooterButtons;
359360

360-
/// A panel displayed to the side of the body, often hidden on mobile devices.
361+
/// A panel displayed to the side of the [body], often hidden on mobile devices.
361362
///
362363
/// Typically a [Drawer].
363364
final Widget drawer;

packages/flutter/test/material/scaffold_test.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,42 @@ void main() {
305305
await expectBackIcon(tester, TargetPlatform.iOS, Icons.arrow_back_ios);
306306
});
307307
});
308+
309+
group('body size', () {
310+
testWidgets('body size with container', (WidgetTester tester) async {
311+
Key testKey = new UniqueKey();
312+
await tester.pumpWidget(
313+
new Scaffold(body: new Container(key: testKey))
314+
);
315+
expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 600.0));
316+
expect(tester.renderObject/*<RenderBox>*/(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
317+
});
318+
319+
testWidgets('body size with sized container', (WidgetTester tester) async {
320+
Key testKey = new UniqueKey();
321+
await tester.pumpWidget(
322+
new Scaffold(body: new Container(key: testKey, height: 100.0))
323+
);
324+
expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 100.0));
325+
expect(tester.renderObject/*<RenderBox>*/(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
326+
});
327+
328+
testWidgets('body size with centered container', (WidgetTester tester) async {
329+
Key testKey = new UniqueKey();
330+
await tester.pumpWidget(
331+
new Scaffold(body: new Center(child: new Container(key: testKey)))
332+
);
333+
expect(tester.element(find.byKey(testKey)).size, const Size(800.0, 600.0));
334+
expect(tester.renderObject/*<RenderBox>*/(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
335+
});
336+
337+
testWidgets('body size with button', (WidgetTester tester) async {
338+
Key testKey = new UniqueKey();
339+
await tester.pumpWidget(
340+
new Scaffold(body: new FlatButton(key: testKey, onPressed: () { }, child: new Text('')))
341+
);
342+
expect(tester.element(find.byKey(testKey)).size, const Size(88.0, 36.0));
343+
expect(tester.renderObject/*<RenderBox>*/(find.byKey(testKey)).localToGlobal(Point.origin), const Point(0.0, 0.0));
344+
});
345+
});
308346
}

0 commit comments

Comments
 (0)