Commit bb381569 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Improve the docs for CustomMultiChildLayout (#6980)

Fixes #5695
parent cff02a76
......@@ -20,7 +20,7 @@
<excludeFolder url="file://$MODULE_DIR$/test/scheduler/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/services/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/ui/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/widget/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/widgets/packages" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
......
......@@ -20,12 +20,62 @@ class MultiChildLayoutParentData extends ContainerBoxParentDataMixin<RenderBox>
/// A delegate that controls the layout of multiple children.
///
/// Delegates must be idempotent. Specifically, if two delegates are equal, then
/// they must produce the same layout. To change the layout, replace the
/// delegate with a different instance whose [shouldRelayout] returns true when
/// given the previous instance.
///
/// Override [getSize] to control the overall size of the layout. The size of
/// the layout cannot depend on layout properties of the children.
///
/// Override [performLayout] to size and position the children. An
/// implementation of [performLayout] must call [layoutChild] exactly once for
/// each child, but it may call [layoutChild] on children in an arbitrary order.
/// Typically a delegate will use the size returned from [layoutChild] on one
/// child to determine the constraints for [performLayout] on another child or
/// to determine the offset for [positionChild] for that child or another child.
///
/// Override [shouldRelayout] to determine when the layout of the children needs
/// to be recomputed when the delegate changes.
///
/// Used with [MultiChildCustomLayout], the widget for the
/// [RenderCustomMultiChildLayoutBox] render object.
///
/// Subclasses must override some or all of the methods
/// marked "Override this method to..." to provide the constraints and
/// positions of the children.
/// ## Example
///
/// Below is an example implementation of [performLayout] that causes one widget
/// to be the same size as another:
///
/// ```dart
/// @override
/// void performLayout(Size size) {
/// Size followerSize = Size.zero;
///
/// if (hasChild(_Slots.leader) {
/// followerSize = layoutChild(_Slots.leader, new BoxConstraints.loose(size));
/// positionChild(_Slots.leader, Offset.zero);
/// }
///
/// if (hasChild(_Slots.follower)) {
/// layoutChild(_Slots.follower, new BoxConstraints.tight(followerSize));
/// positionChild(_Slots.follower, new Offset(size.width - followerSize.width,
/// size.height - followerSize.height));
/// }
/// }
/// ```
///
/// The delegate gives the leader widget loose constraints, which means the
/// child determines what size to be (subject to fitting within the given size).
/// The delegate then remembers the size of that child and places it in the
/// upper left corner.
///
/// The delegate then gives the follower widget tight constraints, forcing it to
/// match the size of the leader widget. The delegate then places the follower
/// widget in the bottom right corner.
///
/// The leader and follower widget will paint in the order they appear in the
/// child list, regardless of the order in which [layoutChild] is called on
/// them.
abstract class MultiChildLayoutDelegate {
Map<Object, RenderBox> _idToChild;
Set<RenderBox> _debugChildrenNeedingLayout;
......@@ -170,9 +220,10 @@ abstract class MultiChildLayoutDelegate {
}
/// Override this method to return the size of this object given the
/// incoming constraints. The size cannot reflect the instrinsic
/// sizes of the children. If this layout has a fixed width or
/// height the returned size can reflect that; the size will be
/// incoming constraints.
///
/// The size cannot reflect the sizes of the children. If this layout has a
/// fixed width or height the returned size can reflect that; the size will be
/// constrained to the given constraints.
///
/// By default, attempts to size the box to the biggest size
......@@ -180,14 +231,18 @@ abstract class MultiChildLayoutDelegate {
Size getSize(BoxConstraints constraints) => constraints.biggest;
/// Override this method to lay out and position all children given this
/// widget's size. This method must call [layoutChild] for each child. It
/// should also specify the final position of each child with [positionChild].
/// widget's size.
///
/// This method must call [layoutChild] for each child. It should also specify
/// the final position of each child with [positionChild].
void performLayout(Size size);
/// Override this method to return true when the children need to be
/// laid out. This should compare the fields of the current delegate
/// and the given oldDelegate and return true if the fields are such
/// that the layout would be different.
/// laid out.
///
/// This should compare the fields of the current delegate and the given
/// `oldDelegate` and return true if the fields are such that the layout would
/// be different.
bool shouldRelayout(@checked MultiChildLayoutDelegate oldDelegate);
/// Override this method to include additional information in the
......
......@@ -605,7 +605,8 @@ class Padding extends SingleChildRenderObjectWidget {
///
/// See also:
///
/// * [CustomSingleChildLayout].
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
/// a single child.
/// * [Center], which is the same as [Align] but with the [alignment] always
/// set to [FractionalOffset.center].
/// * [FractionallySizedBox], which sizes its child based on a fraction of its own
......@@ -690,13 +691,13 @@ class Center extends Align {
///
/// See also:
///
/// * [SingleChildLayoutDelegate]
/// * [Align] (which sizes itself based on its child's size and positions
/// the child according to a [FractionalOffset] value)
/// * [FractionallySizedBox] (which sizes its child based on a fraction of its own
/// size and positions the child according to a [FractionalOffset] value)
/// * [CustomMultiChildLayout] (which uses a delegate to position multiple
/// children)
/// * [SingleChildLayoutDelegate], which controls the layout of the child.
/// * [Align], which sizes itself based on its child's size and positions
/// the child according to a [FractionalOffset] value.
/// * [FractionallySizedBox], which sizes its child based on a fraction of its own
/// size and positions the child according to a [FractionalOffset] value.
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
/// children.
class CustomSingleChildLayout extends SingleChildRenderObjectWidget {
/// Creates a custom single child layout.
///
......@@ -760,19 +761,31 @@ class LayoutId extends ParentDataWidget<CustomMultiChildLayout> {
}
}
/// A widget that defers the layout of multiple children to a delegate.
/// A widget that uses a delegate to size and position multiple children.
///
/// The delegate can determine the layout constraints for each child and can
/// decide where to position each child. The delegate can also determine the
/// size of the parent, but the size of the parent cannot depend on the sizes of
/// the children.
///
/// [CustomMultiChildLayout] is appropriate when there are complex relationships
/// between the size and positioning of a multiple widgets. To control the
/// layout of a single child, [CustomSingleChildLayout] is more appropriate. For
/// simple cases, such as aligning a widget to one or another edge, the [Stack]
/// widget is more appropriate.
///
/// Each child must be wrapped in a [LayoutId] widget to identify the widget for
/// the delegate.
///
/// See also:
///
/// * [MultiChildLayoutDelegate]
/// * [CustomSingleChildLayout] (which defers the layout of its single child to a delegate)
/// * [Stack]
/// * [Flow]
/// * [MultiChildLayoutDelegate], for details about how to control the layout of
/// the children.
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
/// a single child.
/// * [Stack], which arranges children relative to the edges of the container.
/// * [Flow], which provides paint-time control of its children using transform
/// matrices.
class CustomMultiChildLayout extends MultiChildRenderObjectWidget {
/// Creates a custom multi-child layout.
///
......@@ -1485,11 +1498,14 @@ class BlockBody extends MultiChildRenderObjectWidget {
///
/// See also:
///
/// * [Flow]
/// * [Align], which sizes itself based on its child's size and positions
/// the child according to a [FractionalOffset] value.
/// * [CustomSingleChildLayout]
/// * [CustomMultiChildLayout]
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
/// a single child.
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
/// children.
/// * [Flow], which provides paint-time control of its children using transform
/// matrices.
class Stack extends MultiChildRenderObjectWidget {
/// Creates a stack layout widget.
///
......@@ -2319,10 +2335,12 @@ class Expanded extends Flexible {
///
/// See also:
///
/// * [FlowDelegate]
/// * [Stack]
/// * [CustomSingleChildLayout]
/// * [CustomMultiChildLayout]
/// * [FlowDelegate], which controls the visual presentation of the children.
/// * [Stack], which arranges children relative to the edges of the container.
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
/// a single child.
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
/// children.
class Flow extends MultiChildRenderObjectWidget {
/// Creates a flow layout.
///
......
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