Welcome to follow the official wechat account: FSA Full stack action 👋

Monad layout widgets

A monad layout, as the name suggests, is a widget that contains only one child control

1, the Align (Center)

Center can Center the child control, and by default will stretch as far as possible to fill the parent control:

class CenterDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    returnCenter( child: Icon(Icons.pets), ); }}Copy the code

You can see from the Center source that Center is essentially an alignment that cannot be specified:

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);
}
class Align extends SingleChildRenderObjectWidget {
  /// Creates an alignment widget.
  ///
  /// The alignment defaults to [Alignment.center].
  const Align({
    Key? key,
    this.alignment = Alignment.center,
    this.widthFactor,
    this.heightFactor,
    Widget? child,
  }) : assert(alignment ! =null),
       assert(widthFactor == null || widthFactor >= 0.0),
       assert(heightFactor == null || heightFactor >= 0.0),
       super(key: key, child: child);
Copy the code

Therefore, it is perfectly acceptable to use Align instead of Center:

  • WidthFactor: Specifies that the width of Align is several times the width of the child control
  • HeightFactor: Specifies that the height of Align is several times the height of the child control
  • alignment :
    • Alignment. BottomCenter: The bottom is in the middle
    • Alignment. Center: a center
    • Alignment(x, Y) : The upper left corner is (-1, -1) and the lower right corner is (1, 1)
class AlignDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Center is the alignment with Center
    // return Center(
    // child: Icon(Icons.pets),
    // );
    return Align(
      widthFactor: 5.// The width is 5 times the width of the child
      heightFactor: 5.// The height is 5 times the height of the childalignment: Alignment.center, child: Icon(Icons.pets), ); }}Copy the code

In general, you specify the exact width value directly in the outer Container instead of using widthFactor

2, Padding

Normal widgets do not have a padding property (except Container). If you want to have a padding effect on the child Widget, you can apply a layer of padding to the child Widget. The padding has only two attributes. The padding attribute corresponds to an object of type EdgeInsetsGeometry, which is used in conjunction with the EdgeInsets constant name constructor:

  • Padding: span
    • EdgeInsets. All (8.0): Specifies the internal spacing uniformly
    • EdgeInsets. Symmetric (Horizontal: 8, vertical: 8): The symmetric(horizontal: 8) is separated by a specified internal spacing
    • EdgeInsets. FromLTRB (8, 8, 8, 8): Up, down, left, right, and left separated by specified inner spacing
    • EdgeInsets. Only (left: 8): specifies the spacing in only one direction
class PaddingDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: EdgeInsets.all(8.0),
          child: item("hello lqr"),
        ),
        Divider(height: 1, color: Colors.black),
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
          child: item("hello gitlqr"),
        ),
        Divider(height: 1, color: Colors.black),
        Padding(
          padding: EdgeInsets.fromLTRB(8.8.8.8),
          child: item("hello charylin"),
        ),
        Divider(height: 1, color: Colors.black),
        Padding(
          padding: EdgeInsets.only(left: 8),
          child: item("hello charylin"),
        ),
        Divider(height: 1, color: Colors.black),
      ],
    );
  }

  Widget item(String content) {
    return Text(
      content,
      style: TextStyle(
        fontSize: 30, backgroundColor: Colors.red, color: Colors.white, ), ); }}Copy the code

3, the Container

Container is the most special widget in a Flutter. It can specify dimensions, internal and external spacing, 2D conversion, and so on:

  • Width: the width of the
  • Height: height
  • Alignment: Alignment of child widgets
  • Padding: Inner spacing, type EdgeInsetsGeometry, generally using subclass EdgeInsets
  • Margin: outer spacing, type of EdgeInsetsGeometry, generally using the subclass EdgeInsets
  • Transform: 2D transform, Matrix4 type
  • Color: background color (note: it conflicts with the color in the decoration, only one setting can be selected)
  • decoration:BoxDecoration()
    • Color: background color
    • Border: border style, type BoxBorder, commonly usedBorder.all(width: 5)To specify the
    • BorderRadius: borderRadius geometry type, often usedBorderRadius.circular(8)To specify the
    • boxShadow:BoxShadow()
      • Color: Shadow color
      • Offset: indicates the shadow offset
      • “SpreadRadius” : extends x and y on the basis of offset
class ContainerDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          // width and height are not specified
          width: 200,
          height: 200,
          child: Icon(Icons.pets, size: 50, color: Colors.white),
          // The location of the child element
          alignment: Alignment.topLeft,
          padding: EdgeInsets.all(20),
          margin: EdgeInsets.all(10),
          // Rotate 5 degrees to reduce by half
          transform: Matrix4.rotationZ(degree2Radia(5)).scaled(0.5),
          color: Colors.red,
        ),
        Container(
          width: 200,
          height: 200,
          child: Icon(Icons.accessibility, size: 50, color: Colors.white),
          // Color conflicts with decoration
          // color: Colors.red,
          decoration: BoxDecoration(
              color: Colors.red, / / the background color
              border: Border.all(width: 5, color: Colors.blueAccent), / / frame
              borderRadius: BorderRadius.circular(8), / / the rounded
              boxShadow: [
                BoxShadow(
                  color: Colors.blueGrey, // Shadow color
                  offset: Offset(10.10), // Shadow offset
                  spreadRadius: 5.// extend, equivalent to offset 15,15() [() [() [() }double degree2Radia(double degree) {
    return degree * pi / 180; }}Copy the code

Multiple sub-layout widgets

A multichild layout, as its name implies, is a widget that can contain only multiple child controls

1, Flex

Flex in Flutter is similar to the Flex layout in CSS. It can control the placement of internal child widgets flexibly, but it is not used directly. Instead, it subclasses Row/Column:

  • Row/Column inherits from Flex
  • Row = Flex(direction: Axis.horizontal)
    • MainAxis: Horizontal to the right
    • CrossAxis: straight down
  • Column = Flex(direction: Axis.vertical)
    • MainAxis: Straight down
    • CrossAxis: horizontal to the right

By default, Row takes up as much space horizontally as possible because its mainAxisSize property defaults to mainAxissize.max:

Column and Row are basically the same except in different directions. Therefore, Column will learn about Row as well

class ButtonRowDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /// The Row features:
    ///   -Take up as much space as possible horizontally
    ///     *If you want to wrap content horizontally, you can set mainAxisSize = min
    ///   -Wrap content in the vertical direction
    return Column(
      children: [
        RaisedButton(
          child: Row(
            children: [Icon(Icons.bug_report), Text("Bug report (MainAxisSize. Max)")],
          ),
          onPressed: () {},
        ),
        RaisedButton(
          child: Row(
            mainAxisSize: MainAxisSize.min, // Package contents. The package is Max full parent widget
            children: [Icon(Icons.bug_report), Text("Bug report (MainAxisSize. Min)")], ), onPressed: () {}, ), ], ); }}Copy the code

2, Row

Row focuses on spindle and cross axis alignment:

  • MainAxisAlignment:
    • Start: Place elements one by one at the beginning of the spindle
    • End: The end position of the spindle places the elements one by one
    • Center: aligns the center point of the spindle
    • SpaceBetween: the spaceBetween the left and right sides is 0, and the other elements are bisected between each other
    • SpaceAround: The space between the left and right is half the space between the other elements
    • Spaceinstituted: All spacing evenly divides space
  • CrossAxisAlignment:
    • Start: aligns the starting position of the cross axis
    • End: Align the end position of the cross axis
    • Center: Center point alignment (default)
    • Baseline: baseline alignment (must have text)
      • TextBaseline must be specified to use baseline alignment, otherwise an error will be reported.
    • Stretch: Make the Row occupy as much space as possible on the cross axis, and stretch the height of the cross axis of all child widgets to the maximum
class RowDemo1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        itemRow("start", MainAxisAlignment.start, "center", CrossAxisAlignment.center),
        itemRow("end", MainAxisAlignment.end, "center", CrossAxisAlignment.center),
        itemRow("center", MainAxisAlignment.center, "center", CrossAxisAlignment.center),
        itemRow("spaceBetween", MainAxisAlignment.spaceBetween, "center", CrossAxisAlignment.center),
        itemRow("spaceAround", MainAxisAlignment.spaceAround, "center", CrossAxisAlignment.center),
        itemRow("spaceEvenly", MainAxisAlignment.spaceEvenly, "center", CrossAxisAlignment.center),
      ],
    );
  }

  Widget itemRow(
      String mainAxisAlignmentStr,
      MainAxisAlignment mainAxisAlignment,
      String crossAxisAlignmentStr,
      CrossAxisAlignment crossAxisAlignment) {
    return Container(
      height: 120,
      margin: const EdgeInsets.only(bottom: 8.0),
      color: Colors.pink[100],
      child: Stack(
        fit: StackFit.expand,
        children: [
          Row(
            mainAxisAlignment: mainAxisAlignment,
            crossAxisAlignment: crossAxisAlignment,
            TextDirection: textDirection. LTR, // RTL: typeset from right to left; LTR: Left-to-right layout (default)
            children: [
              Container(width: 80, height: 60, color: Colors.red),
              Container(width: 120, height: 100, color: Colors.green),
              Container(width: 90, height: 80, color: Colors.blue),
              Container(width: 50, height: 120, color: Colors.orange),
            ],
          ),
          Positioned(
            left: 0,
            bottom: 0,
            child: Text(
              "GitLqr >>> main:$mainAxisAlignmentStr , cross:$crossAxisAlignmentStr",
              style: TextStyle(fontSize: 20, backgroundColor: Colors.black54, color: Colors.white), ), ) ], ), ); }}Copy the code

class RowDemo2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Baseline alignment
    return Column(
      children: [
        itemRow("spaceEvenly", MainAxisAlignment.spaceEvenly, "start", CrossAxisAlignment.start),
        itemRow("spaceEvenly", MainAxisAlignment.spaceEvenly, "center", CrossAxisAlignment.center),
        itemRow("spaceEvenly", MainAxisAlignment.spaceEvenly, "end", CrossAxisAlignment.end),
        itemRow("spaceEvenly", MainAxisAlignment.spaceEvenly, "stretch", CrossAxisAlignment.stretch),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.baseline,
          // Alphabetic and ideographic baselines are almost the same
          textBaseline: TextBaseline.ideographic,
          children: [
            Container(width: 80,height: 60, color: Colors.red, child: Text("Hellxo", style: TextStyle(fontSize: 20))),
            Container(width: 120, height: 100, color: Colors.green, child: Text("Woxrld", style: TextStyle(fontSize: 30)),),
            Container(width: 90, height: 80, color: Colors.blue, child: Text("abxc", style: TextStyle(fontSize: 12))),
            Container(width: 50, height: 120, color: Colors.orange, child: Text("cxba", style: TextStyle(fontSize: 40[, [, [, [, [, [ } Widget itemRow(String mainAxisAlignmentStr,
      MainAxisAlignment mainAxisAlignment,
      String crossAxisAlignmentStr,
      CrossAxisAlignment crossAxisAlignment) {
    return Container(
      height: 140,
      margin: const EdgeInsets.only(bottom: 8.0),
      color: Colors.pink[100],
      child: Stack(
        fit: StackFit.expand,
        children: [
          Row(
            mainAxisAlignment: mainAxisAlignment,
            crossAxisAlignment: crossAxisAlignment,
            TextDirection: textDirection. LTR, // RTL: typeset from right to left; LTR: Left-to-right layout (default)
            children: [
              Container(width: 80, height: 60, color: Colors.red),
              Container(width: 120, height: 100, color: Colors.green),
              Container(width: 90, height: 80, color: Colors.blue),
              Container(width: 50, height: 120, color: Colors.orange),
            ],
          ),
          Positioned(
            left: 0,
            bottom: 0,
            child: Text(
              "GitLqr >>> main:$mainAxisAlignmentStr , cross:$crossAxisAlignmentStr",
              style: TextStyle(fontSize: 20, backgroundColor: Colors.black54, color: Colors.white), ), ) ], ), ); }}Copy the code

The effect of the final group is CrossAxisAlignment. The baseline, you can see no matter how much text, at the bottom of the letter “x” are in a line, this is the baseline alignment. It is important to note that use CrossAxisAlignment. Baseline must specify both baseline textBaseline (the default value is null), Its value TextBaseline. Ideographic is almost the same as TextBaseline. Alphabetic

3, the Column

Column and Row both inherit from Flex and are almost identical except for the orientation differences. Here are just a few of the formatting differences:

  • Row: indicates the typesetting direction TextDirection
    • RTL: Typeset from right to left
    • LTR: Left-to-right layout (default)
  • Column: VerticalDirection
    • Up: Typesetting from bottom to top
    • Down: Typesetting from top to bottom (default)
class ColumnDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(children: [
      Expanded(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.center,
          verticalDirection: VerticalDirection.down,
          // up: from bottom to top; Down: Typesetting from top to bottom (default)
          children: [
            Container(width: 80, height: 60, color: Colors.red),
            Container(width: 120, height: 100, color: Colors.green),
            Container(width: 90, height: 80, color: Colors.blue),
            Container(width: 50, height: 120, color: Colors.orange),
            Text(
              "GitLqr >>> VerticalDirection.down",
              style: TextStyle(fontSize: 20, backgroundColor: Colors.black54, color: Colors.white),
            ),
          ],
        ),
      ),
      Expanded(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.center,
          verticalDirection: VerticalDirection.up,
          // up: from bottom to top; Down: Typesetting from top to bottom (default)
          children: [
            Container(width: 80, height: 60, color: Colors.red),
            Container(width: 120, height: 100, color: Colors.green),
            Container(width: 90, height: 80, color: Colors.blue),
            Container(width: 50, height: 120, color: Colors.orange),
            Text(
              "GitLqr >>> VerticalDirection.up",
              style: TextStyle(fontSize: 20, backgroundColor: Colors.black54, color: Colors.white), ), ], ), ), ]); }}Copy the code

4, Flexible (Expanded)

  • Attribute in Flexible:

    • Fit: Fill mode
      • Tight: The child control forces the available space to be filled
      • Loose: The child control only occupies its own size
    • Flex: This works when fit is tight
      • When flex is not specified: Stretch Flexible equally until the available space is filled, equivalent to 1 flex
      • When Flex is specified: Stretch Flexible in flex proportions until the available space is filled, at which point the original width is invalid
  • Expanded = Flexible(fit: FlexFit.tight)

    • Stretch the child control when Flex(Row/Column) has space available
    • Shrink the child control when it exceeds Flex(Row/Column) space
class ExpandedDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        item1(),
        tip("Flexible fit: FlexFit.tight flex: 1"),
        item2(),
        tip("Expanded flex: 1 , flex: 1 (width: 120)"),
        item3(),
        tip("Expanded flex: 1 , flex: 2 (width: 10000)"),]); } Widget item1() {return Row(
      children: [
        Flexible(
          fit: FlexFit.tight,
          flex: 1,
          child: Container(width: 80, height: 60, color: Colors.red),
        ),
        Flexible(
          fit: FlexFit.tight,
          flex: 1,
          child: Container(width: 120, height: 100, color: Colors.green),
        ),
        Container(width: 90, height: 80, color: Colors.blue),
        Container(width: 50, height: 120, color: Colors.orange),
      ],
    );
  }

  Widget item2() {
    return Row(
      children: [
        Expanded(
          flex: 1,
          child: Container(width: 80, height: 60, color: Colors.red),
        ),
        Expanded(
          flex: 1,
          child: Container(width: 120, height: 100, color: Colors.green),
        ),
        Container(width: 90, height: 80, color: Colors.blue),
        Container(width: 50, height: 120, color: Colors.orange),
      ],
    );
  }

  Widget item3() {
    return Row(
      children: [
        Expanded(
          flex: 1,
          child: Container(width: 80, height: 60, color: Colors.red),
        ),
        Expanded(
          flex: 2,
          child: Container(width: 10000, height: 100, color: Colors.green),
        ),
        Container(width: 90, height: 80, color: Colors.blue),
        Container(width: 50, height: 120, color: Colors.orange),
      ],
    );
  }

  Widget tip(String content) {
    return Text(
      "GitLqr >>> $content",
      style: TextStyle(
        fontSize: 20, color: Colors.white, backgroundColor: Colors.black54, ), ); }}Copy the code

5, the Stack

The Stack allows the child widgets to be stacked on top of each other. The default size is the size of the package content, and the properties are:

  • Alignment: Specifies the starting position of the alignmentAll the child widgets
    • Positioned(Widget) : that’s rightA single child widgetsTo locate
  • Stretch the child elements to the largest possible size
  • Overflow: How to handle overflow, e.g. : overflow is still displayed, can be usedOverflow.visible
class StackDemo1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: AlignmentDirectional.bottomStart,
      // fit: StackFit.expand,
      overflow: Overflow.visible,
      children: [
        Image.asset("assets/images/FSA_QR.png"),
        Positioned(
          left: 20,
          bottom: - 50,
          child: Container(width: 150, height: 150, color: Colors.red),
        ),
        Positioned(
          right: 0,
          child: Text(
            "lqr",
            style: TextStyle(fontSize: 30, color: Colors.white, backgroundColor: Colors.black), ), ) ], ); }}Copy the code

3. Comprehensive cases

class StackDemo2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Image.asset("assets/images/FSA_QR.png"),
        Positioned(
          left: 0,
          right: 0,
          bottom: 0,
          child: Container(
            padding: EdgeInsets.symmetric(horizontal: 8.0),
            color: Color.fromARGB(160.0.0.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  "Welcome to the public account: FSA full stack Behavior",
                  style: TextStyle(fontSize: 20, color: Colors.white),
                ),
                IconButton(
                  icon: Icon(Icons.favorite),
                  color: Colors.red,
                  onPressed: () => print("Click on favorites"() [() [() [() [() [() }}Copy the code

If this article is helpful to you, please click on my wechat official number: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, but also iOS, Python and other articles, which may have some skills you want to know about oh ~