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
7bafe54a
Commit
7bafe54a
authored
Nov 05, 2015
by
Hans Muller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added LayoutId widget, MultiChildLayoutDelegate.isChild()
parent
9bc64540
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
115 additions
and
57 deletions
+115
-57
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+52
-35
custom_layout.dart
packages/flutter/lib/src/rendering/custom_layout.dart
+24
-16
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+33
-0
custom_multi_child_layout_test.dart
...ages/unit/test/widget/custom_multi_child_layout_test.dart
+6
-6
No files found.
packages/flutter/lib/src/material/scaffold.dart
View file @
7bafe54a
...
@@ -14,15 +14,10 @@ import 'tool_bar.dart';
...
@@ -14,15 +14,10 @@ import 'tool_bar.dart';
const
double
_kFloatingActionButtonMargin
=
16.0
;
// TODO(hmuller): should be device dependent
const
double
_kFloatingActionButtonMargin
=
16.0
;
// TODO(hmuller): should be device dependent
const
int
_kBodyIndex
=
0
;
enum
_Child
{
body
,
toolBar
,
bottomSheet
,
snackBar
,
floatingActionButton
}
const
int
_kToolBarIndex
=
1
;
const
int
_kBottomSheetIndex
=
2
;
const
int
_kSnackBarIndex
=
3
;
const
int
_kFloatingActionButtonIndex
=
4
;
class
_ScaffoldLayout
extends
MultiChildLayoutDelegate
{
class
_ScaffoldLayout
extends
MultiChildLayoutDelegate
{
void
performLayout
(
Size
size
,
BoxConstraints
constraints
,
int
childCount
)
{
void
performLayout
(
Size
size
,
BoxConstraints
constraints
)
{
assert
(
childCount
==
5
);
// This part of the layout has the same effect as putting the toolbar and
// This part of the layout has the same effect as putting the toolbar and
// body in a column and making the body flexible. What's different is that
// body in a column and making the body flexible. What's different is that
...
@@ -30,12 +25,19 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
...
@@ -30,12 +25,19 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
// so the toolbar's shadow is drawn on top of the body.
// so the toolbar's shadow is drawn on top of the body.
final
BoxConstraints
toolBarConstraints
=
constraints
.
loosen
().
tightenWidth
(
size
.
width
);
final
BoxConstraints
toolBarConstraints
=
constraints
.
loosen
().
tightenWidth
(
size
.
width
);
final
Size
toolBarSize
=
layoutChild
(
_kToolBarIndex
,
toolBarConstraints
);
Size
toolBarSize
=
Size
.
zero
;
final
double
bodyHeight
=
size
.
height
-
toolBarSize
.
height
;
final
BoxConstraints
bodyConstraints
=
toolBarConstraints
.
tightenHeight
(
bodyHeight
);
if
(
isChild
(
_Child
.
toolBar
))
{
layoutChild
(
_kBodyIndex
,
bodyConstraints
);
toolBarSize
=
layoutChild
(
_Child
.
toolBar
,
toolBarConstraints
);
positionChild
(
_kToolBarIndex
,
Point
.
origin
);
positionChild
(
_Child
.
toolBar
,
Point
.
origin
);
positionChild
(
_kBodyIndex
,
new
Point
(
0.0
,
toolBarSize
.
height
));
}
if
(
isChild
(
_Child
.
body
))
{
final
double
bodyHeight
=
size
.
height
-
toolBarSize
.
height
;
final
BoxConstraints
bodyConstraints
=
toolBarConstraints
.
tightenHeight
(
bodyHeight
);
layoutChild
(
_Child
.
body
,
bodyConstraints
);
positionChild
(
_Child
.
body
,
new
Point
(
0.0
,
toolBarSize
.
height
));
}
// The BottomSheet and the SnackBar are anchored to the bottom of the parent,
// The BottomSheet and the SnackBar are anchored to the bottom of the parent,
// they're as wide as the parent and are given their intrinsic height.
// they're as wide as the parent and are given their intrinsic height.
...
@@ -47,24 +49,39 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
...
@@ -47,24 +49,39 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
// by _kFloatingActionButtonMargin.
// by _kFloatingActionButtonMargin.
final
BoxConstraints
fullWidthConstraints
=
constraints
.
loosen
().
tightenWidth
(
size
.
width
);
final
BoxConstraints
fullWidthConstraints
=
constraints
.
loosen
().
tightenWidth
(
size
.
width
);
final
Size
bottomSheetSize
=
layoutChild
(
_kBottomSheetIndex
,
fullWidthConstraints
);
Size
bottomSheetSize
=
Size
.
zero
;
final
Size
snackBarSize
=
layoutChild
(
_kSnackBarIndex
,
fullWidthConstraints
);
Size
snackBarSize
=
Size
.
zero
;
final
Size
fabSize
=
layoutChild
(
_kFloatingActionButtonIndex
,
constraints
.
loosen
());
positionChild
(
_kBottomSheetIndex
,
new
Point
(
0.0
,
size
.
height
-
bottomSheetSize
.
height
));
if
(
isChild
(
_Child
.
bottomSheet
))
{
positionChild
(
_kSnackBarIndex
,
new
Point
(
0.0
,
size
.
height
-
snackBarSize
.
height
));
bottomSheetSize
=
layoutChild
(
_Child
.
bottomSheet
,
fullWidthConstraints
);
positionChild
(
_Child
.
bottomSheet
,
new
Point
(
0.0
,
size
.
height
-
bottomSheetSize
.
height
));
final
double
fabX
=
size
.
width
-
fabSize
.
width
-
_kFloatingActionButtonMargin
;
}
double
fabY
=
size
.
height
-
fabSize
.
height
-
_kFloatingActionButtonMargin
;
if
(
snackBarSize
.
height
>
0.0
)
if
(
isChild
(
_Child
.
snackBar
))
{
fabY
=
math
.
min
(
fabY
,
size
.
height
-
snackBarSize
.
height
-
fabSize
.
height
-
_kFloatingActionButtonMargin
);
snackBarSize
=
layoutChild
(
_Child
.
snackBar
,
fullWidthConstraints
);
if
(
bottomSheetSize
.
height
>
0.0
)
positionChild
(
_Child
.
snackBar
,
new
Point
(
0.0
,
size
.
height
-
snackBarSize
.
height
));
fabY
=
math
.
min
(
fabY
,
size
.
height
-
bottomSheetSize
.
height
-
fabSize
.
height
/
2.0
);
}
positionChild
(
_kFloatingActionButtonIndex
,
new
Point
(
fabX
,
fabY
));
if
(
isChild
(
_Child
.
floatingActionButton
))
{
final
Size
fabSize
=
layoutChild
(
_Child
.
floatingActionButton
,
constraints
.
loosen
());
final
double
fabX
=
size
.
width
-
fabSize
.
width
-
_kFloatingActionButtonMargin
;
double
fabY
=
size
.
height
-
fabSize
.
height
-
_kFloatingActionButtonMargin
;
if
(
snackBarSize
.
height
>
0.0
)
fabY
=
math
.
min
(
fabY
,
size
.
height
-
snackBarSize
.
height
-
fabSize
.
height
-
_kFloatingActionButtonMargin
);
if
(
bottomSheetSize
.
height
>
0.0
)
fabY
=
math
.
min
(
fabY
,
size
.
height
-
bottomSheetSize
.
height
-
fabSize
.
height
/
2.0
);
positionChild
(
_Child
.
floatingActionButton
,
new
Point
(
fabX
,
fabY
));
}
}
}
}
}
final
_ScaffoldLayout
_scaffoldLayout
=
new
_ScaffoldLayout
();
final
_ScaffoldLayout
_scaffoldLayout
=
new
_ScaffoldLayout
();
void
_addIfNonNull
(
List
<
LayoutId
>
children
,
Widget
child
,
Object
childId
)
{
if
(
child
!=
null
)
children
.
add
(
new
LayoutId
(
child:
child
,
id:
childId
));
}
class
Scaffold
extends
StatelessComponent
{
class
Scaffold
extends
StatelessComponent
{
Scaffold
({
Scaffold
({
Key
key
,
Key
key
,
...
@@ -92,14 +109,14 @@ class Scaffold extends StatelessComponent {
...
@@ -92,14 +109,14 @@ class Scaffold extends StatelessComponent {
child:
snackBar
child:
snackBar
);
);
}
}
return
new
CustomMultiChildLayout
(<
Widget
>[
materialBody
??
new
Container
(
height:
0.0
),
final
List
<
LayoutId
>
children
=
new
List
<
LayoutId
>();
paddedToolBar
??
new
Container
(
height:
0.0
),
_addIfNonNull
(
children
,
materialBody
,
_Child
.
body
);
bottomSheet
??
new
Container
(
height:
0.0
),
_addIfNonNull
(
children
,
paddedToolBar
,
_Child
.
toolBar
);
constrainedSnackBar
??
new
Container
(
height:
0.0
),
_addIfNonNull
(
children
,
bottomSheet
,
_Child
.
bottomSheet
);
floatingActionButton
??
new
Container
(
height:
0.0
)
_addIfNonNull
(
children
,
constrainedSnackBar
,
_Child
.
snackBar
);
],
_addIfNonNull
(
children
,
floatingActionButton
,
_Child
.
floatingActionButton
);
delegate:
_scaffoldLayout
);
return
new
CustomMultiChildLayout
(
children
,
delegate:
_scaffoldLayout
);
}
}
}
}
packages/flutter/lib/src/rendering/custom_layout.dart
View file @
7bafe54a
...
@@ -5,10 +5,12 @@
...
@@ -5,10 +5,12 @@
import
'box.dart'
;
import
'box.dart'
;
import
'object.dart'
;
import
'object.dart'
;
class
_MultiChildParentData
extends
ContainerBoxParentDataMixin
<
RenderBox
>
{
}
class
MultiChildLayoutParentData
extends
ContainerBoxParentDataMixin
<
RenderBox
>
{
Object
id
;
}
abstract
class
MultiChildLayoutDelegate
{
abstract
class
MultiChildLayoutDelegate
{
final
List
<
RenderBox
>
_indexToChild
=
<
RenderBox
>[]
;
final
Map
<
Object
,
RenderBox
>
_idToChild
=
new
Map
<
Object
,
RenderBox
>()
;
/// Returns the size of this object given the incomming constraints.
/// Returns the size of this object given the incomming constraints.
/// The size cannot reflect the instrinsic sizes of the children.
/// The size cannot reflect the instrinsic sizes of the children.
...
@@ -16,41 +18,47 @@ abstract class MultiChildLayoutDelegate {
...
@@ -16,41 +18,47 @@ abstract class MultiChildLayoutDelegate {
/// can reflect that.
/// can reflect that.
Size
getSize
(
BoxConstraints
constraints
)
=>
constraints
.
biggest
;
Size
getSize
(
BoxConstraints
constraints
)
=>
constraints
.
biggest
;
/// True if a non-null LayoutChild was provided for the specified id.
bool
isChild
(
Object
childId
)
=>
_idToChild
[
childId
]
!=
null
;
/// Ask the child to update its layout within the limits specified by
/// Ask the child to update its layout within the limits specified by
/// the constraints parameter. The child's size is returned.
/// the constraints parameter. The child's size is returned.
Size
layoutChild
(
int
childIndex
,
BoxConstraints
constraints
)
{
Size
layoutChild
(
Object
childId
,
BoxConstraints
constraints
)
{
final
RenderBox
child
=
_indexToChild
[
childIndex
];
final
RenderBox
child
=
_idToChild
[
childId
];
assert
(
child
!=
null
);
child
.
layout
(
constraints
,
parentUsesSize:
true
);
child
.
layout
(
constraints
,
parentUsesSize:
true
);
return
child
.
size
;
return
child
.
size
;
}
}
/// Specify the child's origin relative to this origin.
/// Specify the child's origin relative to this origin.
void
positionChild
(
int
childIndex
,
Point
position
)
{
void
positionChild
(
Object
childId
,
Point
position
)
{
final
RenderBox
child
=
_indexToChild
[
childIndex
];
final
RenderBox
child
=
_idToChild
[
childId
];
final
_MultiChildParentData
childParentData
=
child
.
parentData
;
assert
(
child
!=
null
);
final
MultiChildLayoutParentData
childParentData
=
child
.
parentData
;
childParentData
.
position
=
position
;
childParentData
.
position
=
position
;
}
}
void
_callPerformLayout
(
Size
size
,
BoxConstraints
constraints
,
RenderBox
firstChild
)
{
void
_callPerformLayout
(
Size
size
,
BoxConstraints
constraints
,
RenderBox
firstChild
)
{
RenderBox
child
=
firstChild
;
RenderBox
child
=
firstChild
;
while
(
child
!=
null
)
{
while
(
child
!=
null
)
{
_indexToChild
.
add
(
child
);
final
MultiChildLayoutParentData
childParentData
=
child
.
parentData
;
final
_MultiChildParentData
childParentData
=
child
.
parentData
;
assert
(
childParentData
.
id
!=
null
);
_idToChild
[
childParentData
.
id
]
=
child
;
child
=
childParentData
.
nextSibling
;
child
=
childParentData
.
nextSibling
;
}
}
performLayout
(
size
,
constraints
,
_indexToChild
.
length
);
performLayout
(
size
,
constraints
);
_i
ndex
ToChild
.
clear
();
_i
d
ToChild
.
clear
();
}
}
/// Layout and position all children given this widget's size and the specified
/// Layout and position all children given this widget's size and the specified
/// constraints. This method must apply layoutChild() to each child. It should
/// constraints. This method must apply layoutChild() to each child. It should
/// specify the final position of each child with positionChild().
/// specify the final position of each child with positionChild().
void
performLayout
(
Size
size
,
BoxConstraints
constraints
,
int
childCount
);
void
performLayout
(
Size
size
,
BoxConstraints
constraints
);
}
}
class
RenderCustomMultiChildLayoutBox
extends
RenderBox
class
RenderCustomMultiChildLayoutBox
extends
RenderBox
with
ContainerRenderObjectMixin
<
RenderBox
,
_MultiChild
ParentData
>,
with
ContainerRenderObjectMixin
<
RenderBox
,
MultiChildLayout
ParentData
>,
RenderBoxContainerDefaultsMixin
<
RenderBox
,
_MultiChild
ParentData
>
{
RenderBoxContainerDefaultsMixin
<
RenderBox
,
MultiChildLayout
ParentData
>
{
RenderCustomMultiChildLayoutBox
({
RenderCustomMultiChildLayoutBox
({
List
<
RenderBox
>
children
,
List
<
RenderBox
>
children
,
MultiChildLayoutDelegate
delegate
MultiChildLayoutDelegate
delegate
...
@@ -60,8 +68,8 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
...
@@ -60,8 +68,8 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
}
}
void
setupParentData
(
RenderBox
child
)
{
void
setupParentData
(
RenderBox
child
)
{
if
(
child
.
parentData
is
!
_MultiChild
ParentData
)
if
(
child
.
parentData
is
!
MultiChildLayout
ParentData
)
child
.
parentData
=
new
_MultiChild
ParentData
();
child
.
parentData
=
new
MultiChildLayout
ParentData
();
}
}
MultiChildLayoutDelegate
get
delegate
=>
_delegate
;
MultiChildLayoutDelegate
get
delegate
=>
_delegate
;
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
7bafe54a
...
@@ -288,6 +288,39 @@ class CustomOneChildLayout extends OneChildRenderObjectWidget {
...
@@ -288,6 +288,39 @@ class CustomOneChildLayout extends OneChildRenderObjectWidget {
}
}
}
}
class
LayoutId
extends
ParentDataWidget
{
LayoutId
({
Key
key
,
Widget
child
,
this
.
id
})
:
super
(
key:
key
,
child:
child
);
final
Object
id
;
void
debugValidateAncestor
(
Widget
ancestor
)
{
assert
(()
{
'LayoutId must placed inside a CustomMultiChildLayout'
;
return
ancestor
is
CustomMultiChildLayout
;
});
}
void
applyParentData
(
RenderObject
renderObject
)
{
assert
(
renderObject
.
parentData
is
MultiChildLayoutParentData
);
final
MultiChildLayoutParentData
parentData
=
renderObject
.
parentData
;
if
(
parentData
.
id
!=
id
)
{
parentData
.
id
=
id
;
AbstractNode
targetParent
=
renderObject
.
parent
;
if
(
targetParent
is
RenderObject
)
targetParent
.
markNeedsLayout
();
}
}
void
debugFillDescription
(
List
<
String
>
description
)
{
super
.
debugFillDescription
(
description
);
description
.
add
(
'id:
$id
'
);
}
}
class
CustomMultiChildLayout
extends
MultiChildRenderObjectWidget
{
class
CustomMultiChildLayout
extends
MultiChildRenderObjectWidget
{
CustomMultiChildLayout
(
List
<
Widget
>
children
,
{
CustomMultiChildLayout
(
List
<
Widget
>
children
,
{
Key
key
,
Key
key
,
...
...
packages/unit/test/widget/custom_multi_child_layout_test.dart
View file @
7bafe54a
...
@@ -14,16 +14,16 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
...
@@ -14,16 +14,16 @@ class TestMultiChildLayoutDelegate extends MultiChildLayoutDelegate {
Size
performLayoutSize
;
Size
performLayoutSize
;
BoxConstraints
performLayoutConstraints
;
BoxConstraints
performLayoutConstraints
;
int
performLayoutChildCount
;
Size
performLayoutSize0
;
Size
performLayoutSize0
;
Size
performLayoutSize1
;
Size
performLayoutSize1
;
bool
performLayoutIsChild
;
void
performLayout
(
Size
size
,
BoxConstraints
constraints
,
int
childCount
)
{
void
performLayout
(
Size
size
,
BoxConstraints
constraints
)
{
performLayoutSize
=
size
;
performLayoutSize
=
size
;
performLayoutConstraints
=
constraints
;
performLayoutConstraints
=
constraints
;
performLayoutChildCount
=
childCount
;
performLayoutSize0
=
layoutChild
(
0
,
constraints
);
performLayoutSize0
=
layoutChild
(
0
,
constraints
);
performLayoutSize1
=
layoutChild
(
1
,
constraints
);
performLayoutSize1
=
layoutChild
(
1
,
constraints
);
performLayoutIsChild
=
isChild
(
'fred'
);
}
}
}
}
...
@@ -33,8 +33,8 @@ void main() {
...
@@ -33,8 +33,8 @@ void main() {
TestMultiChildLayoutDelegate
delegate
=
new
TestMultiChildLayoutDelegate
();
TestMultiChildLayoutDelegate
delegate
=
new
TestMultiChildLayoutDelegate
();
tester
.
pumpWidget
(
new
Center
(
tester
.
pumpWidget
(
new
Center
(
child:
new
CustomMultiChildLayout
([
child:
new
CustomMultiChildLayout
([
new
Container
(
width:
150.0
,
height:
100.0
),
new
LayoutId
(
id:
0
,
child:
new
Container
(
width:
150.0
,
height:
100.0
)
),
new
Container
(
width:
100.0
,
height:
200.0
)
new
LayoutId
(
id:
1
,
child:
new
Container
(
width:
100.0
,
height:
200.0
)
)
],
],
delegate:
delegate
delegate:
delegate
)
)
...
@@ -51,11 +51,11 @@ void main() {
...
@@ -51,11 +51,11 @@ void main() {
expect
(
delegate
.
performLayoutConstraints
.
maxWidth
,
800.0
);
expect
(
delegate
.
performLayoutConstraints
.
maxWidth
,
800.0
);
expect
(
delegate
.
performLayoutConstraints
.
minHeight
,
0.0
);
expect
(
delegate
.
performLayoutConstraints
.
minHeight
,
0.0
);
expect
(
delegate
.
performLayoutConstraints
.
maxHeight
,
600.0
);
expect
(
delegate
.
performLayoutConstraints
.
maxHeight
,
600.0
);
expect
(
delegate
.
performLayoutChildCount
,
2
);
expect
(
delegate
.
performLayoutSize0
.
width
,
150.0
);
expect
(
delegate
.
performLayoutSize0
.
width
,
150.0
);
expect
(
delegate
.
performLayoutSize0
.
height
,
100.0
);
expect
(
delegate
.
performLayoutSize0
.
height
,
100.0
);
expect
(
delegate
.
performLayoutSize1
.
width
,
100.0
);
expect
(
delegate
.
performLayoutSize1
.
width
,
100.0
);
expect
(
delegate
.
performLayoutSize1
.
height
,
200.0
);
expect
(
delegate
.
performLayoutSize1
.
height
,
200.0
);
expect
(
delegate
.
performLayoutIsChild
,
false
);
});
});
});
});
}
}
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