Commit 5766cdac authored by Hans Muller's avatar Hans Muller Committed by GitHub

Define LayoutWidgetBuilder in terms of BoxConstraints instead of Size (#4578)

parent 661740d2
...@@ -90,7 +90,8 @@ class _PestoDemoState extends State<PestoDemo> { ...@@ -90,7 +90,8 @@ class _PestoDemoState extends State<PestoDemo> {
) )
], ],
flexibleSpace: new LayoutBuilder( flexibleSpace: new LayoutBuilder(
builder: (BuildContext context, Size size) { builder: (BuildContext context, BoxConstraints constraints) {
final Size size = constraints.biggest;
double appBarHeight = size.height - statusBarHeight; double appBarHeight = size.height - statusBarHeight;
double bestHeight = _kLogoImages.keys.lastWhere( double bestHeight = _kLogoImages.keys.lastWhere(
(double height) => appBarHeight >= height (double height) => appBarHeight >= height
...@@ -293,7 +294,12 @@ class _RecipePageState extends State<_RecipePage> { ...@@ -293,7 +294,12 @@ class _RecipePageState extends State<_RecipePage> {
return new Stack( return new Stack(
children: <Widget>[ children: <Widget>[
_buildContainer(context), _buildContainer(context),
new Padding( new Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: new Container(
height: kToolBarHeight + statusBarHeight,
padding: new EdgeInsets.only(top: statusBarHeight), padding: new EdgeInsets.only(top: statusBarHeight),
child: new AppBar( child: new AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
...@@ -316,6 +322,7 @@ class _RecipePageState extends State<_RecipePage> { ...@@ -316,6 +322,7 @@ class _RecipePageState extends State<_RecipePage> {
] ]
) )
) )
)
] ]
); );
} }
......
...@@ -178,8 +178,9 @@ class AppBar extends StatelessWidget { ...@@ -178,8 +178,9 @@ class AppBar extends StatelessWidget {
return ((appBarHeight - statusBarHeight) / tabBarHeight).clamp(0.0, 1.0); return ((appBarHeight - statusBarHeight) / tabBarHeight).clamp(0.0, 1.0);
} }
Widget _buildForSize(BuildContext context, Size size) { Widget _buildForSize(BuildContext context, BoxConstraints constraints) {
assert(size.height < double.INFINITY); assert(constraints.maxHeight < double.INFINITY);
final Size size = constraints.biggest;
final double statusBarHeight = MediaQuery.of(context).padding.top; final double statusBarHeight = MediaQuery.of(context).padding.top;
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
...@@ -274,6 +275,8 @@ class AppBar extends StatelessWidget { ...@@ -274,6 +275,8 @@ class AppBar extends StatelessWidget {
child: appBar child: appBar
) )
); );
} else if (flexibleSpace != null) {
appBar = new Positioned(top: 0.0, left: 0.0, right: 0.0, child: appBar);
} }
if (flexibleSpace != null) { if (flexibleSpace != null) {
......
...@@ -9,14 +9,15 @@ import 'package:flutter/rendering.dart'; ...@@ -9,14 +9,15 @@ import 'package:flutter/rendering.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
/// The signature of the [LayoutBuilder] builder function. /// The signature of the [LayoutBuilder] builder function.
typedef Widget LayoutWidgetBuilder(BuildContext context, Size size); typedef Widget LayoutWidgetBuilder(BuildContext context, BoxConstraints constraints);
/// Builds a widget tree that can depend on the parent widget's size. /// Builds a widget tree that can depend on the parent widget's size.
/// ///
/// Similar to the [Builder] widget except that the framework calls the [builder] /// Similar to the [Builder] widget except that the framework calls the [builder]
/// function at layout time and provides the parent widget's size. This is useful /// function at layout time and provides the parent widget's constraints. This
/// when the parent constrains the child's size and doesn't depend on the child's /// is useful when the parent constrains the child's size and doesn't depend on
/// intrinsic size. /// the child's intrinsic size. The LayoutBuilder's final size will match its
/// child's size.
class LayoutBuilder extends RenderObjectWidget { class LayoutBuilder extends RenderObjectWidget {
/// Creates a widget that defers its building until layout. /// Creates a widget that defers its building until layout.
/// ///
...@@ -89,20 +90,16 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren ...@@ -89,20 +90,16 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
return 0.0; return 0.0;
} }
@override
bool get sizedByParent => true;
@override
void performResize() {
size = constraints.biggest;
}
@override @override
void performLayout() { void performLayout() {
if (callback != null) if (callback != null)
invokeLayoutCallback(callback); invokeLayoutCallback(callback);
if (child != null) if (child != null) {
child.layout(constraints.loosen()); child.layout(constraints, parentUsesSize: true);
size = constraints.constrain(child.size);
} else {
size = constraints.biggest;
}
} }
@override @override
...@@ -169,7 +166,7 @@ class _LayoutBuilderElement extends RenderObjectElement { ...@@ -169,7 +166,7 @@ class _LayoutBuilderElement extends RenderObjectElement {
owner.lockState(() { owner.lockState(() {
Widget built; Widget built;
try { try {
built = widget.builder(this, constraints.biggest); built = widget.builder(this, constraints);
debugWidgetBuilderValue(widget, built); debugWidgetBuilderValue(widget, built);
} catch (e, stack) { } catch (e, stack) {
_debugReportException('building $widget', e, stack); _debugReportException('building $widget', e, stack);
......
...@@ -10,19 +10,20 @@ void main() { ...@@ -10,19 +10,20 @@ void main() {
testWidgets('LayoutBuilder parent size', (WidgetTester tester) async { testWidgets('LayoutBuilder parent size', (WidgetTester tester) async {
Size layoutBuilderSize; Size layoutBuilderSize;
Key childKey = new UniqueKey(); Key childKey = new UniqueKey();
Key parentKey = new UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
new Center( new Center(
child: new SizedBox( child: new ConstrainedBox(
width: 100.0, constraints: const BoxConstraints(maxWidth: 100.0, maxHeight: 200.0),
height: 200.0,
child: new LayoutBuilder( child: new LayoutBuilder(
builder: (BuildContext context, Size size) { key: parentKey,
layoutBuilderSize = size; builder: (BuildContext context, BoxConstraints constraints) {
layoutBuilderSize = constraints.biggest;
return new SizedBox( return new SizedBox(
key: childKey, key: childKey,
width: size.width / 2.0, width: layoutBuilderSize.width / 2.0,
height: size.height / 2.0 height: layoutBuilderSize.height / 2.0
); );
} }
) )
...@@ -31,21 +32,26 @@ void main() { ...@@ -31,21 +32,26 @@ void main() {
); );
expect(layoutBuilderSize, const Size(100.0, 200.0)); expect(layoutBuilderSize, const Size(100.0, 200.0));
RenderBox box = tester.renderObject(find.byKey(childKey)); RenderBox parentBox = tester.renderObject(find.byKey(parentKey));
expect(box.size, equals(const Size(50.0, 100.0))); expect(parentBox.size, equals(const Size(50.0, 100.0)));
RenderBox childBox = tester.renderObject(find.byKey(childKey));
expect(childBox.size, equals(const Size(50.0, 100.0)));
}); });
testWidgets('LayoutBuilder stateful child', (WidgetTester tester) async { testWidgets('LayoutBuilder stateful child', (WidgetTester tester) async {
Size layoutBuilderSize; Size layoutBuilderSize;
StateSetter setState; StateSetter setState;
Key childKey = new UniqueKey(); Key childKey = new UniqueKey();
Key parentKey = new UniqueKey();
double childWidth = 10.0; double childWidth = 10.0;
double childHeight = 20.0; double childHeight = 20.0;
await tester.pumpWidget( await tester.pumpWidget(
new LayoutBuilder( new Center(
builder: (BuildContext context, Size size) { child: new LayoutBuilder(
layoutBuilderSize = size; key: parentKey,
builder: (BuildContext context, BoxConstraints constraints) {
layoutBuilderSize = constraints.biggest;
return new StatefulBuilder( return new StatefulBuilder(
builder: (BuildContext context, StateSetter setter) { builder: (BuildContext context, StateSetter setter) {
setState = setter; setState = setter;
...@@ -58,19 +64,24 @@ void main() { ...@@ -58,19 +64,24 @@ void main() {
); );
} }
) )
)
); );
expect(layoutBuilderSize, equals(const Size(800.0, 600.0))); expect(layoutBuilderSize, equals(const Size(800.0, 600.0)));
RenderBox box = tester.renderObject(find.byKey(childKey)); RenderBox parentBox = tester.renderObject(find.byKey(parentKey));
expect(box.size, equals(const Size(10.0, 20.0))); expect(parentBox.size, equals(const Size(10.0, 20.0)));
RenderBox childBox = tester.renderObject(find.byKey(childKey));
expect(childBox.size, equals(const Size(10.0, 20.0)));
setState(() { setState(() {
childWidth = 100.0; childWidth = 100.0;
childHeight = 200.0; childHeight = 200.0;
}); });
await tester.pump(); await tester.pump();
box = tester.renderObject(find.byKey(childKey)); parentBox = tester.renderObject(find.byKey(parentKey));
expect(box.size, equals(const Size(100.0, 200.0))); expect(parentBox.size, equals(const Size(100.0, 200.0)));
childBox = tester.renderObject(find.byKey(childKey));
expect(childBox.size, equals(const Size(100.0, 200.0)));
}); });
testWidgets('LayoutBuilder stateful parent', (WidgetTester tester) async { testWidgets('LayoutBuilder stateful parent', (WidgetTester tester) async {
...@@ -89,12 +100,12 @@ void main() { ...@@ -89,12 +100,12 @@ void main() {
width: childWidth, width: childWidth,
height: childHeight, height: childHeight,
child: new LayoutBuilder( child: new LayoutBuilder(
builder: (BuildContext context, Size size) { builder: (BuildContext context, BoxConstraints constraints) {
layoutBuilderSize = size; layoutBuilderSize = constraints.biggest;
return new SizedBox( return new SizedBox(
key: childKey, key: childKey,
width: size.width, width: layoutBuilderSize.width,
height: size.height height: layoutBuilderSize.height
); );
} }
) )
...@@ -117,10 +128,11 @@ void main() { ...@@ -117,10 +128,11 @@ void main() {
expect(box.size, equals(const Size(100.0, 200.0))); expect(box.size, equals(const Size(100.0, 200.0)));
}); });
testWidgets('LayoutBuilder and Inherited -- do not rebuild when not using inherited', (WidgetTester tester) async { testWidgets('LayoutBuilder and Inherited -- do not rebuild when not using inherited', (WidgetTester tester) async {
int built = 0; int built = 0;
Widget target = new LayoutBuilder( Widget target = new LayoutBuilder(
builder: (BuildContext context, Size size) { builder: (BuildContext context, BoxConstraints constraints) {
built += 1; built += 1;
return new Container(); return new Container();
} }
...@@ -143,7 +155,7 @@ void main() { ...@@ -143,7 +155,7 @@ void main() {
testWidgets('LayoutBuilder and Inherited -- do rebuild when using inherited', (WidgetTester tester) async { testWidgets('LayoutBuilder and Inherited -- do rebuild when using inherited', (WidgetTester tester) async {
int built = 0; int built = 0;
Widget target = new LayoutBuilder( Widget target = new LayoutBuilder(
builder: (BuildContext context, Size size) { builder: (BuildContext context, BoxConstraints constraints) {
built += 1; built += 1;
MediaQuery.of(context); MediaQuery.of(context);
return new Container(); return new Container();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment