- The layout Widget for Flutter
- Related blog series: The Flutter and Dart series
- related
Demo
Address:Making the address - Layout of the class
Widget
Will contain one or more childrenwidget
, different layout classesWidget
pairswidget
Layout (layout
) in different ways - Previous articleMentioned:
Widget
In factElement
Configuration data ofWidget
The function is to describe aUI
Element of a configuration data, while trueUI
Apply colours to a drawing is made up ofElement
Constitute a - in
Flutter
According toWidget
Whether the child nodes need to be included willWidget
It’s divided into three categories, corresponding to three categoriesElement
The following table,
Widget | The corresponding Element | use |
---|---|---|
LeafRenderObjectWidget |
LeafRenderObjectElement |
Widget The leaf node of a tree, used when there are no childrenwidget , usually basiswidget All fall into this category, e.gText ,Image |
SingleChildRenderObjectWidget |
SingleChildRenderObjectElement |
Contains one childWidget , such as:ConstrainedBox ,DecoratedBox Etc. |
MultiChildRenderObjectWidget |
MultiChildRenderObjectElement |
Contains more than one childWidget There is usually onechildren Parameter, accept oneWidget The array. Such asRow ,Column ,Stack Etc. |
The Widget layout class
- Layout of the class
Widget
It means direct or indirect inheritance.MultiChildRenderObjectWidget
theWidget
They usually have onechildren
Property is used to receive the childWidget
Widget
Is as follows:Widget
>RenderObjectWidget
>(Leaf/SingleChild/MultiChild)RenderObjectWidget
RenderObjectWidget
Class defines create, updateRenderObject
Methods that subclasses must implement them- For the layout class
Widget
In terms of its layout algorithms are all through the correspondingRenderObject
Object Flutter
There are mainly the following types of layout classesWidget
:- Linear layout
Row
andColumn
- Elastic layout
Flex
- Fluid layout
Wrap
,Flow
- Cascade layout
Stack
,Positioned
- Linear layout
Linear layout
Row
andColumn
It’s a current layoutWidget
Are inherited fromFlex
- A linear layout is a horizontal or vertical layout
The child widgets
- For a linear layout, there is a main axis and a vertical axis. If the layout is horizontal, then the main axis is the horizontal direction and the vertical axis is the vertical direction. If the layout is vertical, then the main axis is vertical and the vertical axis is horizontal
Row
The principal axis of is the horizontal direction,Column
The main axis of the vertical direction, cut both attributes and use are the same- The source code defined below is as follows:
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
})
Column({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
})
Copy the code
The related attributes are as follows
mainAxisAlignment
The arrangement of child widgets in the main axis is referred to as a component for convenience
/ / the default value
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start
Copy the code
start
Son:widgets
I’m going to go to the starting point of the principal axisend
Son:widgets
I’m going to go to the end of the principal axiscenter
: all of the childrenwidgets
Centered alignmentspaceBetween
: Evenly distributed, adjacentwidgets
The distance is the same. The first one in each rowwidgets
Align with the beginning of the line, last on each linewidgets
Align with the end of the linespaceAround
: Evenly distributed, adjacentwidgets
The distance is the same. The first one in each rowwidgets
The distance to the beginning of the line and the last one in each linewidgets
The distance to the end of the line will be adjacentwidgets
Half the distance betweenspaceEvenly
: Evenly distributed, adjacentwidgets
The distance is the same. The first one in each rowwidgets
The distance to the beginning of the line and the last one in each linewidgets
Distance to the end of the line and adjacencywidgets
The same distance between
attribute | The effect |
---|---|
start |
|
end |
|
center |
|
spaceBetween |
|
spaceAround |
|
spaceEvenly |
mainAxisSize
/ / the default value
MainAxisSize mainAxisSize = MainAxisSize.max
Copy the code
- said
Row
Space taken up in the main axis (horizontal) direction, default isMainAxisSize.max
max
Represents as much horizontal space as possible, at this time regardless of the childwidgets
How much horizontal space is actually occupied,Row
The width of is always equal to the maximum width in the horizontal direction;MainAxisSize.min
Means to occupy as little horizontal space as possible, whenwidgets
Does not occupy the horizontal remaining space, thenRow
The actual width of is equal to all of the childrenwidgets
The horizontal space occupied
verticalDirection
Indicates the alignment of the vertical axis of the Row. The default value is down, indicating that the Row is from top to bottom. Up means from the bottom up
/ / the default value
VerticalDirection verticalDirection = VerticalDirection.down
Copy the code
crossAxisAlignment
- Said the child
Widgets
The alignment in the vertical direction,Row
The height of PI is equal to PIWidgets
The height of the highest child element in crossAxisAlignment
The reference frame of isverticalDirection
/ / the default value
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center
/** ** Verticaldirection. down crossAxisAlignment. Start Crossaxisalignment. start refers to bottom alignment * crosSAXisalignment. end and crosSAXisalignment. start are opposite */
Copy the code
- when
VerticalDirection.down
When,crossAxisAlignment
The enumerated values are as follows start
: top to itend
: Bottom to itcenter
: Center against itstretch
: on the side axis, the childWidget
The height of phi is stretched to phiRow
Is the same heightbaseline
: no matterVerticalDirection
What is the value, sonWidget
The top andRow
The top of it
textDirection
Indicates the horizontal layout order of the child widgets (left to right or right to left). The default is the text orientation of the system’s current Locale (for example, left to right for Chinese and English, but right to left for Arabic).
TextDirection textDirection
/** * LTR: left to right * RTL: right to left */
Copy the code
textBaseline
Use the horizontal line on its text, see for details
TextBaseline textBaseline
/** * Alphabetic: used to align common alphabetic baselines ** ideographic: used to align ideographic baselines */
Copy the code
Use the code
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
textBaseline: TextBaseline.ideographic,
children: <Widget>[
new Container(width: 80.0, height:80.0, color: Colors.red,),
new Container(width: 80.0, height:90.0, color: Colors.green,),
new Container(width: 80.0, height:100.0, color: Colors.blue,),
],
)
Copy the code
Pay special attention to
In Row and Column, an overflow error is reported if the child widget is out of screen range
Elastic layout
- Elastic layout allows children
widget
The parent container space is allocated proportionally Flutter
The elastic layout is mainly throughFlex
andExpanded
To coordinate the implementationFlex
Children can be arranged horizontally or verticallywidget
- If the spindle direction is known, use it
Row
orColumn
Because theRow
andColumn
All inherit fromFlex
, parameters are basically the same, so it can be usedFlex
The place must be usableRow
orColumn
Flex
It’s powerful on its own, and it can work withExpanded
With elastic layout, we will discuss onlyFlex
Properties related to elastic layout (other properties have already been introducedRow
andColumn
Was introduced at the time.)
Flex
Flex({
Key key,
// The direction of the elastic layout
@required this.direction,
this.mainAxisAlignment = MainAxisAlignment.start,
this.mainAxisSize = MainAxisSize.max,
this.crossAxisAlignment = CrossAxisAlignment.center,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
this.textBaseline,
List<Widget> children = const <Widget>[],
})
// direction
// Horizontal direction
Axis direction = Axis.horizontal
// Vertical direction, default vertical direction
Axis direction = Axis.vertical
Copy the code
Flex inherits from MultiChildRenderObjectWidget, corresponding RenderObject RenderFlex, RenderFlex implemented in its layout algorithm
Expanded
You can scale the space taken up by Row, Column, and Flex child widgets
class Expanded extends Flexible {
const Expanded({
Key key,
int flex = 1.@required Widget child,
}) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}
Copy the code
Flex is the elastic coefficient. If it is 0 or NULL, child is inelastic, that is, the space not occupied by expansion. If greater than 0, all Expanded partitions the total free space of the spindle in proportion to their Flex
Row(
children: <Widget>[
Container(width: 80.0, height:80.0, color: Colors.red,),
Expanded(
flex: 1,
child: Container(width: 80.0, height:80.0, color: Colors.blue,),
),
Expanded(
flex: 1,
child: Container(width: 80.0, height:80.0, color: Colors.yellow,),
)
],
),
Copy the code
Fluid layout
- It was mentioned above that
Row
andColumn
In, if the sonwidget
Out of screen range, an overflow error is reported - This is because
Row
There is only one line by default and no line folding if it goes beyond the screen - We call the layout that folds automatically when you go beyond the screen a streaming layout
Flutter
Through theWrap
andFlow
To support streaming layouts
Wrap
Wrap({
Key key,
this.direction = Axis.horizontal,
this.alignment = WrapAlignment.start,
this.spacing = 0.0.this.runAlignment = WrapAlignment.start,
this.runSpacing = 0.0.this.crossAxisAlignment = WrapCrossAlignment.start,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
List<Widget> children = const <Widget>[],
})
Copy the code
You can see that many of the properties in Wrap are the same as those in Row, so instead of going over them here, we’ll focus on the properties that are unique to Wrap
alignment
The way the child widgets are on the main axis
/ / the default value
this.alignment = WrapAlignment.start
// Values: start, end, center, spaceBetween, spaceAround, spaceinstituted
Copy the code
runAlignment
Child widgets on the vertical axis on their way
/ / the default value
this.runAlignment = WrapAlignment.start
// Values: start, end, center, spaceBetween, spaceAround, spaceinstituted
Copy the code
spacing
Spacing of sub-widgets in the spindle direction: spacing: 10
runSpacing
Spacing of child widgets in the vertical axis: runSpacing: 10
Flow
- It’s rarely used
Flow
Because it is too complex, you need to implement it yourselfwidget
In many scenarios, the first thing to consider isWrap
Whether the requirements are met Flow
It is mainly used in UI that requires custom layout or in scenes that require high performance (such as animation)Flow
It has the following advantages:- Good performance:
Flow
Is a rightchild
Very efficient controls for size and position adjustment,Flow
Use transformation matrix pairschild
Optimizations were made when the position was adjusted - in
Flow
After positioning, ifchild
Has changed in size or position inFlowDelegate
In thepaintChildren()
Method callcontext.paintChild
I’m going to redraw, andcontext.paintChild
The transformation matrix was used in the redraw without actual adjustmentWidget
Position. - Flexibility: Because we need to implement it ourselves
FlowDelegate
thepaintChildren()
Method, so we need to calculate each one ourselveswidget
The location, therefore, can be implemented custom layout.
- Good performance:
- Disadvantages:
- Complex to use.
- Can’t adapt
widget
Size, must be specified by the parent container size or overriddenFlowDelegate
thegetSize
Return fixed size
- Here is a simple example code:
class FlowWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
color: Colors.orange,
child: Flow(
delegate: ShowFlowDelegate(margin: EdgeInsets.all(10)),
children: <Widget>[
Container(width: 100.0, height:100.0, color: Colors.red),
Container(width: 100.0, height:100.0, color: Colors.yellow),
Container(width: 100.0, height:100.0, color: Colors.blue),
Container(width: 100.0, height:100.0, color: Colors.cyan),
Container(width: 100.0, height:100.0, color: Colors.pink) ], ), ); }}Copy the code
Implement a class that inherits from FlowDelegate and overwrites the response method
class ShowFlowDelegate extends FlowDelegate {
EdgeInsets margin =EdgeInsets.zero;
ShowFlowDelegate({this.margin});
@override
void paintChildren(FlowPaintingContext context) {
var x = margin.left;
var y = margin.top;
// Calculates the position of each child widget
for (int i = 0; i < context.childCount; i++) {
var w = context.getChildSize(i).width + x + margin.right;
if (w < context.size.width) {
context.paintChild(i,
transform: new Matrix4.translationValues(
x, y, 0.0));
x = w + margin.left;
} else {
x = margin.left;
y += context.getChildSize(i).height + margin.top + margin.bottom;
// Draw child widgets (optimized)
context.paintChild(i,
transform: new Matrix4.translationValues(
x, y, 0.0)); x += context.getChildSize(i).width + margin.left + margin.right; }}}@override
Size getSize(BoxConstraints constraints) {
// Set the Flow size
return Size(double.infinity, 300);
}
@override
bool shouldRepaint(FlowDelegate oldDelegate) {
returnoldDelegate ! =this; }}Copy the code
Cascade layout
- Cascading layout and
Web
Absolute positioning,iOS
In theFrame
The layout is similar to the subwidget
Its position can be determined by the position of the four corners to the parent container - Absolute positioning permit
widget
Stack (in the order declared in the code) Flutter
The use ofStack
andPositioned
To achieve absolute positioning,Stack
Allow the childwidget
Stack,Positioned
Can give a childwidget
positioning
Stack
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
Copy the code
alignment
Determines the position of the child widgets in the Stack
/ / the default value
this.alignment = AlignmentDirectional.topStart
// Start and end are horizontal directions, and top and bottom are vertical directions
static const AlignmentDirectional topStart = AlignmentDirectional(1.0.1.0);
static const AlignmentDirectional topCenter = AlignmentDirectional(0.0.1.0);
static const AlignmentDirectional topEnd = AlignmentDirectional(1.0.1.0);
static const AlignmentDirectional centerStart = AlignmentDirectional(1.0.0.0);
static const AlignmentDirectional center = AlignmentDirectional(0.0.0.0);
static const AlignmentDirectional centerEnd = AlignmentDirectional(1.0.0.0);
static const AlignmentDirectional bottomStart = AlignmentDirectional(1.0.1.0);
static const AlignmentDirectional bottomCenter = AlignmentDirectional(0.0.1.0);
static const AlignmentDirectional bottomEnd = AlignmentDirectional(1.0.1.0);
// You can also use specific numerical scale positioning, set the value between 0 and 1
AlignmentDirectional(0.8.0.9)
Copy the code
textDirection
Determines the reference frame of alignment
/ / LTR by default
textDirection: TextDirection.ltr
LTR; // textDirection is textdirection. LTR
// The textDirection value is textDirection. RTL. The alignment start indicates the right and end indicates the left
Copy the code
fit
How do unpositioned child widgets fit into the Stack size
/ / the default value
this.fit = StackFit.loose
// stackfit.loose indicates the size to use the child widgets
// StackFit. Expand specifies the size to expand to the Stack
Copy the code
overflow
Decide how to display child widgets that exceed the Stack display space
/ / the default value
this.overflow = Overflow.clip
// Overflow. clipped (hidden)
// overflow. visible will not be clipped
Copy the code
Use the sample
Stack(
// alignment: AlignmentDirectional.center,
alignment: AlignmentDirectional(0.8.0.8),
textDirection: TextDirection.ltr,
fit: StackFit.loose,
overflow: Overflow.visible,
children: <Widget>[
Container(width: 100.0, height:100.0, color: Colors.red),
Container(width: 100.0, height:100.0, color: Colors.yellow),
],
)
Copy the code
Positioned
The position and size of the Frame in tourists and iOS are the same, positioning and size of the Widget is set according to the upper, lower, left and right and the width and height
const Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
Copy the code
Left, top, right, and bottom represent the distances from the left, top, right, and bottom sides of the Stack, respectively. Width and height specify the width and height of the positioning element
Note that width and height here have slightly different meanings than elsewhere. This is used to position widgets with the left, top, right, and bottom attributes. For example, in the horizontal direction, you can specify only two of the left, right, and width attributes. If left and width are specified, right is automatically calculated (left+width). If three attributes are specified at the same time, an error is reported
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
// The widget is displayed according to the alignment Settings
Container(child: Text('https', style: TextStyle(color: Colors.red)), color: Colors.yellow,),
// The widget displays independent alignment based on the left and top and width Settings. The actual width is 80
Positioned(
left: 10,
top: 30,
width: 80,
child: Container(width: 100.0, height:100.0, color: Colors.red),
),
Positioned(
right: 10,
bottom: 50,
child: Container(width: 100.0, height:100.0, color: Colors.blue),
)
],
),
Copy the code
At this point, all the layout related widgets in Flutter have been learned…… Next comes the container class Widget
reference
- Flutter of actual combat
- Because Chinese website
Please scan the following wechat official account and subscribe to my blog!