1. Padding

A widget that insets its child by the given padding.

 1.1 Introduction


Padding is also used quite a bit in Flutter, as a basic control with a very single function, to set the padding property for child nodes. Anyone who has written the other end of the spectrum understands this property, which is to set the inner margin property, the blank area of the inner margin, which is also part of the widget.


There is no separate Margin control in Flutter, there is a margin property in Container, see the source code for the implementation of margin.

if (margin != null)
  current = new Padding(padding: margin, child: current);


Not surprisingly, the distinction between margin as well as padding is downplayed in Flutter, and margin is essentially implemented by padding as well.

 1.2 Layout behavior

 The layout of Padding is divided into two cases:


  • When child is empty, a region with width left+right and height top+bottom is created;

  • When child is not empty, Padding passes layout constraints to child, reducing the size of child’s layout based on the padding property set. Padding then resizes itself to the size of the child with the padding attribute set, creating the blank area around the child.

 1.3 Succession relationships

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Padding


As you can see from the inheritance relationship, the Padding control is a basic control, unlike the Container, which utilizes the margin and padding properties to implement the Container.


1.3.1 About SingleChildRenderObjectWidget


SingleChildRenderObjectWidget is a subclass of RenderObjectWidgets for limiting to only one child node. It only provides storage for the child, not the actual update logic.


1.3.2 About RenderObjectWidgets


RenderObjectWidgets provide configuration for the RenderObjectElement, which contains the (wrap) RenderObject, which is the element that provides the actual rendering in the application.

 1.4 Example code

 Example code directly on the official example, very simple:

new Padding(
  padding: new EdgeInsets.all(8.0),
  child: const Card(child: const Text('Hello World!')),
)

  The example sets an inner margin of width 8 for the Card.

 1.5 Source code parsing

 The constructor is as follows:

const Padding({
    Key key,
    @required this.padding,
    Widget child,
  })

  Contains a padding attribute that is fairly simple.

 1.5.1 Attribute parsing


padding: the type of padding is EdgeInsetsGeometry , EdgeInsetsGeometry is the base class of EdgeInsets and EdgeInsetsDirectional. In actual use does not involve internationalization, such as adapting to the Arab region, etc., generally use EdgeInsets. EdgeInsetsDirectional just look at the name of the direction of the direction-related, so its four margins are not limited to the top and bottom of the left and right, but according to the direction to determine.

 1.5.2 Source Code

@override
  RenderPadding createRenderObject(BuildContext context) {
    return new RenderPadding(
      padding: padding,
      textDirection: Directionality.of(context),
   );
}


The Padding creation function is actually carried out by RenderPadding .


About the actual layout performance of RenderPadding when child is null:

if (child == null) {
  size = constraints.constrain(new Size(
    _resolvedPadding.left + _resolvedPadding.right,
    _resolvedPadding.top + _resolvedPadding.bottom
  ));
  return;
}


Returns an area with width _resolvedPadding.left + _resolvedPadding.right and height _resolvedPadding.top + _resolvedPadding.bottom.


When child is not null, it undergoes three processes, i.e., resizing child, resizing child position, and resizing Padding, to finally achieve the actual layout.

 
final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding);
child.layout(innerConstraints, parentUsesSize: true);
 
final BoxParentData childParentData = child.parentData;
childParentData.offset = new Offset(_resolvedPadding.left, _resolvedPadding.top);

 
size = constraints.constrain(new Size(
  _resolvedPadding.left + child.size.width + _resolvedPadding.right,
  _resolvedPadding.top + child.size.height + _resolvedPadding.bottom
));


By this point, the padding layout behavior described above makes sense.

 1.6 Scenarios of use


Padding itself is pretty simple, and it can be used basically anywhere spacing is needed. If in a single spacing scenario, the use of Padding than Container cost is a little smaller, after all, Container contains multiple widgets, Padding can be achieved, Container can be achieved, only that Container is more complex.

2. Align

A widget that aligns its child within itself and optionally sizes itself based on the child’s size.

 2.1 Introduction


In the other end of the development, Align is generally used as a property of the control, and not taken out as a separate control.Align itself to achieve the function is not complicated, set the child alignment, such as center, left, right, etc., and according to the child size to adjust their own size.

 2.2 Layout behavior

 Align’s layout behavior is divided into two cases:


  • When widthFactor and heightFactor are null, Align will try to extend itself according to the constraints when they have constraints, and will adjust to the size of the child when there are no constraints;

  • When widthFactor or heightFactor is not null, Align will extend its own size according to the factor attribute, for example, if widthFactor is set to 2.0, then the width of Align will be twice as wide as child.


Why does Align have this layout behavior? The reason is simple, if you set the alignment, the inner alignment cannot be determined if the outer element size is not determined. Therefore, there will be width and height factors, expanding to the maximum size according to the outer limit, and adjusting to the child size when the outer layer is uncertain.

 2.3 Succession relationships

Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Align


As you can see, Align, like Padding, is a very basic component, and the Container uses Align to implement the align property.

 2.4 Example code

new Align(
  alignment: Alignment.center,
  widthFactor: 2.0,
  heightFactor: 2.0,
  child: new Text("Align"),
)


The example is still very simple, set a width and height of the child twice the area of the Align, its child in the center.

 2.5 Source code parsing

const Align({
    Key key,
    this.alignment: Alignment.center,
    this.widthFactor,
    this.heightFactor,
    Widget child
  })


Align’s constructor is basically a width and height factor, alignment property. In daily use, the aspect factor property is not used much. If it is a complex layout, the Container’s internal align attribute can achieve the same effect.

 2.5.1 Attribute parsing


Alignment: Alignment, generally use the default system provides 9 ways, but not that only these 9 kinds, such as the following definition. The 9 ways provided by the system are only predefined.

/// The top left corner.
static const Alignment topLeft = const Alignment(-1.0, -1.0);


Alignment actually contains two properties, where the first parameter, -1.0 is left alignment and 1.0 is right alignment, and the second parameter, -1.0 is top alignment and 1.0 is bottom alignment. Based on this rule, we can also customize the alignment we need, for example

 
static const Alignment rightHalfBottom = alignment: const Alignment(1.0, 0.5),


widthFactor: width factor, if set, the width of Align is the width of child multiplied by this value, can’t be negative.


heightFactor: the height factor, if set, the height of the Align is the height of the child multiplied by this value, it can’t be negative.

 2.5.2 Source Code

@override
  RenderPositionedBox createRenderObject(BuildContext context) {
    return new RenderPositionedBox(
      alignment: alignment,
      widthFactor: widthFactor,
      heightFactor: heightFactor,
      textDirection: Directionality.of(context),
    );
  }


The actual constructor call for Align is RenderPositionedBox .


The layout of the RenderPositionedBox behaves as follows:

 
final bool shrinkWrapWidth = _widthFactor != null || constraints.maxWidth == double.infinity;
final bool shrinkWrapHeight = _heightFactor != null || constraints.maxHeight == double.infinity;

if (child != null) {
  
  child.layout(constraints.loosen(), parentUsesSize: true);
  size = constraints.constrain(new Size(shrinkWrapWidth ? child.size.width * (_widthFactor ?? 1.0) : double.infinity,
                                        shrinkWrapHeight ? child.size.height * (_heightFactor ?? 1.0) : double.infinity));
  alignChild();
} else {
 
  size = constraints.constrain(new Size(shrinkWrapWidth ? 0.0 : double.infinity,
                                        shrinkWrapHeight ? 0.0 : double.infinity));
}

  2.6 Scenarios of use


Generally used in alignment scenarios, such as the need to right-align or bottom-align and so on. Container can realize all the functions it can achieve.

3. Center


Center is inherited from Align, only the alignment is set to Alignment.center, other attributes such as widthFactor, heightFactor, layout behavior, are exactly the same as Align, we will not do a separate introduction. Center source code is as follows, without setting the alignment attribute, because the default alignment of Align is centered.

class Center extends Align {
  /// Creates a widget that centers its child.
  const Center({ Key key, double widthFactor, double heightFactor, Widget child })
    : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}

By lzz

Leave a Reply

Your email address will not be published. Required fields are marked *