Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
b38927e7
Commit
b38927e7
authored
May 03, 2016
by
Hans Muller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
LayoutBuilder widget (#3670)
* LayoutBuilder Widget
parent
c9010c91
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
336 additions
and
15 deletions
+336
-15
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+4
-2
debug.dart
packages/flutter/lib/src/widgets/debug.dart
+16
-0
framework.dart
packages/flutter/lib/src/widgets/framework.dart
+1
-12
layout_builder.dart
packages/flutter/lib/src/widgets/layout_builder.dart
+192
-0
widgets.dart
packages/flutter/lib/widgets.dart
+3
-1
layout_builder_test.dart
packages/flutter/test/widget/layout_builder_test.dart
+120
-0
No files found.
packages/flutter/lib/src/widgets/basic.dart
View file @
b38927e7
...
...
@@ -2897,9 +2897,11 @@ class Builder extends StatelessWidget {
/// Called to obtain the child widget.
///
/// This function is invoked whe
th
er this widget is included in its parent's
/// This function is invoked whe
nev
er this widget is included in its parent's
/// build and the old widget (if any) that it synchronizes with has a distinct
/// object identity.
/// object identity. Typically the parent's build method will construct
/// a new tree of widgets and so a new Builder child will not be [identical]
/// to the corresponding old one.
final
WidgetBuilder
builder
;
@override
...
...
packages/flutter/lib/src/widgets/debug.dart
View file @
b38927e7
...
...
@@ -4,6 +4,7 @@
import
'dart:collection'
;
import
'package:flutter/foundation.dart'
;
import
'framework.dart'
;
import
'table.dart'
;
...
...
@@ -99,3 +100,18 @@ bool debugCheckHasTable(BuildContext context) {
});
return
true
;
}
void
debugWidgetBuilderValue
(
Widget
widget
,
Widget
built
)
{
assert
(()
{
if
(
built
==
null
)
{
throw
new
FlutterError
(
'A build function returned null.
\n
'
'The offending widget is:
$widget
\n
'
'Build functions must never return null. '
'To return an empty space that causes the building widget to fill available room, return "new Container()". '
'To return an empty space that takes as little room as possible, return "new Container(width: 0.0, height: 0.0)".'
);
}
return
true
;
});
}
packages/flutter/lib/src/widgets/framework.dart
View file @
b38927e7
...
...
@@ -1513,18 +1513,7 @@ abstract class ComponentElement extends BuildableElement {
Widget
built
;
try
{
built
=
_builder
(
this
);
assert
(()
{
if
(
built
==
null
)
{
throw
new
FlutterError
(
'A build function returned null.
\n
'
'The offending widget is:
$widget
\n
'
'Build functions must never return null. '
'To return an empty space that causes the building widget to fill available room, return "new Container()". '
'To return an empty space that takes as little room as possible, return "new Container(width: 0.0, height: 0.0)".'
);
}
return
true
;
});
debugWidgetBuilderValue
(
widget
,
built
);
}
catch
(
e
,
stack
)
{
_debugReportException
(
'building
$_widget
'
,
e
,
stack
);
built
=
new
ErrorWidget
(
e
);
...
...
packages/flutter/lib/src/widgets/layout_builder.dart
0 → 100644
View file @
b38927e7
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'debug.dart'
;
import
'framework.dart'
;
import
'package:flutter/rendering.dart'
;
/// The signature of the [LayoutBuilder] builder function.
typedef
Widget
LayoutWidgetBuilder
(
BuildContext
context
,
Size
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]
/// function at layout time and provides the parent widget's size. This is useful
/// when the parent constrains the child's size and doesn't depend on the child's
/// intrinsic size.
class
LayoutBuilder
extends
RenderObjectWidget
{
LayoutBuilder
({
Key
key
,
this
.
builder
})
:
super
(
key:
key
);
/// Called at layout time to construct the widget tree. The builder must not
/// return null.
final
LayoutWidgetBuilder
builder
;
@override
_LayoutBuilderElement
createElement
()
=>
new
_LayoutBuilderElement
(
this
);
@override
_RenderLayoutBuilder
createRenderObject
(
BuildContext
context
)
=>
new
_RenderLayoutBuilder
();
}
class
_RenderLayoutBuilder
extends
RenderBox
with
RenderObjectWithChildMixin
<
RenderBox
>
{
_RenderLayoutBuilder
({
LayoutCallback
callback
})
:
_callback
=
callback
;
LayoutCallback
get
callback
=>
_callback
;
LayoutCallback
_callback
;
void
set
callback
(
LayoutCallback
value
)
{
if
(
value
==
_callback
)
return
;
_callback
=
value
;
markNeedsLayout
();
}
double
getIntrinsicWidth
(
BoxConstraints
constraints
)
=>
constraints
.
constrainWidth
();
double
getIntrinsicHeight
(
BoxConstraints
constraints
)
=>
constraints
.
constrainHeight
();
@override
double
getMinIntrinsicWidth
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
debugAssertIsValid
());
return
getIntrinsicWidth
(
constraints
);
}
@override
double
getMaxIntrinsicWidth
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
debugAssertIsValid
());
return
getIntrinsicWidth
(
constraints
);
}
@override
double
getMinIntrinsicHeight
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
debugAssertIsValid
());
return
getIntrinsicHeight
(
constraints
);
}
@override
double
getMaxIntrinsicHeight
(
BoxConstraints
constraints
)
{
assert
(
constraints
.
debugAssertIsValid
());
return
getIntrinsicHeight
(
constraints
);
}
@override
bool
get
sizedByParent
=>
true
;
@override
void
performResize
()
{
size
=
constraints
.
biggest
;
}
@override
void
performLayout
()
{
if
(
callback
!=
null
)
invokeLayoutCallback
(
callback
);
if
(
child
!=
null
)
child
.
layout
(
constraints
.
loosen
(),
parentUsesSize:
false
);
}
@override
bool
hitTestChildren
(
HitTestResult
result
,
{
Point
position
})
{
return
child
?.
hitTest
(
result
,
position:
position
)
??
false
;
}
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
if
(
child
!=
null
)
context
.
paintChild
(
child
,
offset
);
}
}
class
_LayoutBuilderElement
extends
RenderObjectElement
{
_LayoutBuilderElement
(
LayoutBuilder
widget
)
:
super
(
widget
);
@override
LayoutBuilder
get
widget
=>
super
.
widget
;
@override
_RenderLayoutBuilder
get
renderObject
=>
super
.
renderObject
;
Element
_child
;
@override
void
visitChildren
(
ElementVisitor
visitor
)
{
if
(
_child
!=
null
)
visitor
(
_child
);
}
@override
void
mount
(
Element
parent
,
dynamic
newSlot
)
{
super
.
mount
(
parent
,
newSlot
);
// Creates the renderObject.
renderObject
.
callback
=
_layout
;
// The _child will be built during layout.
}
@override
void
update
(
LayoutBuilder
newWidget
)
{
assert
(
widget
!=
newWidget
);
super
.
update
(
newWidget
);
assert
(
widget
==
newWidget
);
renderObject
.
callback
=
_layout
;
renderObject
.
markNeedsLayout
();
}
@override
void
unmount
()
{
renderObject
.
callback
=
null
;
super
.
unmount
();
}
void
_layout
(
BoxConstraints
constraints
)
{
if
(
widget
.
builder
==
null
)
return
;
owner
.
lockState
(()
{
Widget
built
;
try
{
built
=
widget
.
builder
(
this
,
constraints
.
biggest
);
debugWidgetBuilderValue
(
widget
,
built
);
}
catch
(
e
,
stack
)
{
_debugReportException
(
'building
$widget
'
,
e
,
stack
);
built
=
new
ErrorWidget
(
e
);
}
try
{
_child
=
updateChild
(
_child
,
built
,
null
);
assert
(
_child
!=
null
);
}
catch
(
e
,
stack
)
{
_debugReportException
(
'building
$widget
'
,
e
,
stack
);
built
=
new
ErrorWidget
(
e
);
_child
=
updateChild
(
null
,
built
,
slot
);
}
},
building:
true
);
}
@override
void
insertChildRenderObject
(
RenderObject
child
,
dynamic
slot
)
{
final
RenderObjectWithChildMixin
<
RenderObject
>
renderObject
=
this
.
renderObject
;
assert
(
slot
==
null
);
renderObject
.
child
=
child
;
assert
(
renderObject
==
this
.
renderObject
);
}
@override
void
moveChildRenderObject
(
RenderObject
child
,
dynamic
slot
)
{
assert
(
false
);
}
@override
void
removeChildRenderObject
(
RenderObject
child
)
{
final
_RenderLayoutBuilder
renderObject
=
this
.
renderObject
;
assert
(
renderObject
.
child
==
child
);
renderObject
.
child
=
null
;
assert
(
renderObject
==
this
.
renderObject
);
}
}
void
_debugReportException
(
String
context
,
dynamic
exception
,
StackTrace
stack
)
{
FlutterError
.
reportError
(
new
FlutterErrorDetails
(
exception:
exception
,
stack:
stack
,
library
:
'widgets library'
,
context:
context
));
}
packages/flutter/lib/widgets.dart
View file @
b38927e7
...
...
@@ -3,7 +3,8 @@
// found in the LICENSE file.
/// The Flutter widget framework.
///
///
///
/// To use, import `package:flutter/widgets.dart`.
library
widgets
;
...
...
@@ -25,6 +26,7 @@ export 'src/widgets/gesture_detector.dart';
export
'src/widgets/gridpaper.dart'
;
export
'src/widgets/heroes.dart'
;
export
'src/widgets/implicit_animations.dart'
;
export
'src/widgets/layout_builder.dart'
;
export
'src/widgets/lazy_block.dart'
;
export
'src/widgets/locale_query.dart'
;
export
'src/widgets/media_query.dart'
;
...
...
packages/flutter/test/widget/layout_builder_test.dart
0 → 100644
View file @
b38927e7
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:test/test.dart'
;
void
main
(
)
{
testWidgets
(
'LayoutBuilder parent size'
,
(
WidgetTester
tester
)
{
Size
layoutBuilderSize
;
Key
childKey
=
new
UniqueKey
();
tester
.
pumpWidget
(
new
Center
(
child:
new
SizedBox
(
width:
100.0
,
height:
200.0
,
child:
new
LayoutBuilder
(
builder:
(
BuildContext
context
,
Size
size
)
{
layoutBuilderSize
=
size
;
return
new
SizedBox
(
key:
childKey
,
width:
size
.
width
/
2.0
,
height:
size
.
height
/
2.0
);
}
)
)
)
);
expect
(
layoutBuilderSize
,
const
Size
(
100.0
,
200.0
));
RenderBox
box
=
tester
.
renderObject
(
find
.
byKey
(
childKey
));
expect
(
box
.
size
,
equals
(
const
Size
(
50.0
,
100.0
)));
});
testWidgets
(
'LayoutBuilder stateful child'
,
(
WidgetTester
tester
)
{
Size
layoutBuilderSize
;
StateSetter
setState
;
Key
childKey
=
new
UniqueKey
();
double
childWidth
=
10.0
;
double
childHeight
=
20.0
;
tester
.
pumpWidget
(
new
LayoutBuilder
(
builder:
(
BuildContext
context
,
Size
size
)
{
layoutBuilderSize
=
size
;
return
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setter
)
{
setState
=
setter
;
return
new
SizedBox
(
key:
childKey
,
width:
childWidth
,
height:
childHeight
);
}
);
}
)
);
expect
(
layoutBuilderSize
,
equals
(
const
Size
(
800.0
,
600.0
)));
RenderBox
box
=
tester
.
renderObject
(
find
.
byKey
(
childKey
));
expect
(
box
.
size
,
equals
(
const
Size
(
10.0
,
20.0
)));
setState
(()
{
childWidth
=
100.0
;
childHeight
=
200.0
;
});
tester
.
pump
();
box
=
tester
.
renderObject
(
find
.
byKey
(
childKey
));
expect
(
box
.
size
,
equals
(
const
Size
(
100.0
,
200.0
)));
});
testWidgets
(
'LayoutBuilder stateful parent'
,
(
WidgetTester
tester
)
{
Size
layoutBuilderSize
;
StateSetter
setState
;
Key
childKey
=
new
UniqueKey
();
double
childWidth
=
10.0
;
double
childHeight
=
20.0
;
tester
.
pumpWidget
(
new
Center
(
child:
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setter
)
{
setState
=
setter
;
return
new
SizedBox
(
width:
childWidth
,
height:
childHeight
,
child:
new
LayoutBuilder
(
builder:
(
BuildContext
context
,
Size
size
)
{
layoutBuilderSize
=
size
;
return
new
SizedBox
(
key:
childKey
,
width:
size
.
width
,
height:
size
.
height
);
}
)
);
}
)
)
);
expect
(
layoutBuilderSize
,
equals
(
const
Size
(
10.0
,
20.0
)));
RenderBox
box
=
tester
.
renderObject
(
find
.
byKey
(
childKey
));
expect
(
box
.
size
,
equals
(
const
Size
(
10.0
,
20.0
)));
setState
(()
{
childWidth
=
100.0
;
childHeight
=
200.0
;
});
tester
.
pump
();
box
=
tester
.
renderObject
(
find
.
byKey
(
childKey
));
expect
(
box
.
size
,
equals
(
const
Size
(
100.0
,
200.0
)));
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment