Fletter constraint size position

Let's take a look at the following code:

body: Container(
  width: 400,
  height: 400,
  color: Colors.blue,
  child: Container(
    width: 100,
    height: 100,
    color: Colors.orange,
    child: const FlutterLogo(
      size: 50,
    ),
  ),
),

What we want is 400 * 400 blue bottom, 100 * 100 orange bottom and 50 * 50 fluterlog, but the actual situation is like this:

The reason is that the above components are not satisfied Flutter Constraint condition: will be modified, which can be understood as "child" width And height , are just suggested dimensions. The actual dimensions are determined by the parent object!

  • Fluent , pass constraints down
  • Flutter # pass the recommended size up
  • Finally, the parent calculates the size of each child through the position, and decides where to put the child

After simple processing, we got the layout we should have

body: Container(
  width: 400,
  height: 400,
  color: Colors.blue,
  child: Align(
    //alignment: Alignment(0.5,0.5) is equivalent to alignment: alignment center,
    // alignment: Alignment.bottomCenter,
    child: Container(
      width: 250,
      height: 250,
      color: Colors.orange,
      //There is no rule on where the child should be placed. All can only be placed on the full screen. If you add a Center/Align to make the parent component how to place the child, then you can determine the position and size of the child
      //Center inherits from Align
      child: Center(
        child: const FlutterLogo(
          size: 50,
        ),
      ),
    ),
  ),
),

body: Container(
  width: 400,
  height: 400,
  color: Colors.blue,
  child: Align(
    //alignment: Alignment(0.5,0.5) is equivalent to alignment: alignment center,
    // alignment: Alignment.bottomCenter,
    child: Container(
      width: 250,
      height: 250,
      color: Colors.orange,
      //There is no rule on where the child should be placed. All can only be placed on the full screen. If you add a Center/Align to make the parent component how to place the child, then you can determine the position and size of the child
      //Center inherits from Align
      child: Center(
        child: const FlutterLogo(
          size: 50,
        ),
      ),
    ),
  ),
),

Layout get and set layout constraints

  1. Tight constraint
    constraints:BoxConstraints(w=350.0, h=350.0)
  1. Loose constraint (constraint with minimum value of 0)
    BoxConstraints(0.0<=w<=350.0, 0.0<=h<=350.0)

The size: 9999 set by fluterlog() in the following code has no effect and will be deleted by the parent level Container Correction

body: Center(
  child: Container(
    width: 350,
    height: 350,
    color: Colors.orangeAccent,
    child: FlutterLogo(
      size: 9999,
    ),
  ),
)

Use LayoutBuilder to view constraints at the parent level:

child: LayoutBuilder(
  builder: (BuildContext context, BoxConstraints constraints) {
    print("constraints:$constraints");
    return const FlutterLogo(
      size: 9999,
    );
  },
)

The print result is a tight constraint. No matter how we set the size of the sub component here, it is useless. The parent component will force the size of the sub component to be 350 * 350

I/flutter (13229): constraints:BoxConstraints(w=350.0, h=350.0)

We wrap the LayoutBuilder with a Center component, which can change the constraint of the parent component into a loose constraint, and then tell the parent component where we want to place it; You can control the size of sub components

constraints:BoxConstraints(0.0<=w<=350.0, 0.0<=h<=350.0)

body: Center(
  child: Container(
    width: 350,
    height: 350,
    color: Colors.orangeAccent,
    child: Center(
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          print("constraints:$constraints");
          return const FlutterLogo(
            size: 50,
          );
        },
      ),
    ),
  ),
),
ConstrainedBox: modify our constraints on the premise that our current component meets the constraints of the parent component
  1. First set our constraint as loose constraint. If not, our defined constraint will still be forcibly modified by the parent component
  2. Define our constraints
body: Center(
  child: Container(
    width: 350,
    height: 350,
    color: Colors.orangeAccent,
    child: Center( //1 set our constraint to loose constraint first
      child: ConstrainedBox(
        constraints: const BoxConstraints( //2 define our constraints
            minWidth: 50, maxWidth: 250, minHeight: 50, maxHeight: 250),
        child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) {
            print("constraints:$constraints");
            return const FlutterLogo(
              size: 50,
            );
          },
        ),
      ),
    ),
  ),
),

In the above code, if we don't use the Center component (don't modify the # mandatory constraint # to # loose constraint), then the ConstrainedBox won't work!

//Error demonstration
body: Center(
  child: Container(
    width: 350,
    height: 350,
    color: Colors.orangeAccent,
      //1. First set our constraint to loose constraint; Responsibility doesn't work
      child: ConstrainedBox(
        constraints: const BoxConstraints( //2 define our constraints
            minWidth: 50, maxWidth: 250, minHeight: 50, maxHeight: 250),
        child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) {
            print("constraints:$constraints");
            return const FlutterLogo(
              size: 50,
            );
          },
        ),    
    ),
  ),
),

Layout flex flexible layout:

ListView embedded in Column or Row: error reporting

body: Center(
  child: Container(
    color: Colors.orange,
    width: 250,
    child: Column(
      // mainAxisSize: MainAxisSize.max,
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        ElevatedButton(onPressed: () {}, child: Text("")),
        ListView(
          children: [for (int i = 0; i < 10; i++) Text("List view $i")],
        ),
        ElevatedButton(onPressed: () {}, child: Text("")),
      ],
    ),
  ),
),

RenderBox was not laid out: RenderRepaintBoundary#341bb relayoutBoundary=up5 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1929 pos 12: 'hasSize'

In the above code:

The Column element will first lay out components with {fixed size (with constraints): the heightedbutton component is fixed in height,

ListView component is an elastic component with unlimited height, while Column is also a component with unlimited height; So there will be mistakes! This problem can be solved by wrapping ListView # here! In the final analysis, the reason is: Column itself is an unrestricted element, and the child element is also an unrestricted element except ListView; When two unrestricted elements appear at the same time, {fluent cannot determine the size of the element, and an error will be reported
 

I/flutter (11566): constraints:BoxConstraints(0.0<=w<=250.0, 0.0<=h<=Infinity)

Therefore, when an unconstrained space is nested in an unconstrained space, there is an exception. Wrap the ListView Expand component here to solve this problem: how much expansion occupies the remaining space

body: Center(
  child: Container(
    color: Colors.orange,
    width: 250,
    child: Column(
      // mainAxisSize: MainAxisSize.max,
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        ElevatedButton(onPressed: () {}, child: Text("")),
        Expanded(
          child: ListView(
            children: [
              for (int i = 0; i < 100; i++) Text("List view $i")
            ],
          ),
        ),
        ElevatedButton(onPressed: () {}, child: Text("")),
      ],
    ),
  ),
),

layout Stack stacking: factors affecting the size of} Stack components

There is an interesting phenomenon in the Stack layout

1. When there are  Positioned  components and  other components in the sub components, the size of  Stack components is determined by the maximum  non Positioned components; The following code is determined by the longest Text component

body: Center(
  child: Container(
    color: Colors.blue,
    child: Stack(
      // alignment: Alignment.center,
      alignment: Alignment(-1, 0.75),
      children: [
        Text(
          'You have You have You',
          style: TextStyle(fontSize: 20, color: Colors.orange),
        ),
        Text(
          'GoGoGO',
          style: TextStyle(fontSize: 15, color: Colors.red),
        ),
        Positioned(
          left: 0,
          top: 0,
          child: FlutterLogo(
            size: 250,
          ),
        ),
        Positioned(
          left: 0,
          top: 0,
          child: Container(
            width: 24,
            height: 24,
            color: Colors.black,
          ),
        ),
      ],
    ),
  ),
),

If the child components are all Positioned components, the size of the Stack will occupy the maximum constraint of the parent component

The main reason for this phenomenon is that the Stack component is implemented by the user. If there are other components (non Positioned), then the State has a reference! Therefore, you can layout by reference. If all of them are Positoned, there is no reference; Therefore, it will occupy the parent component;

Of course, it can also be set through Satck # fit attribute: modify the default rule

child: Stack(
  //fit: StackFit.expand, / / maximum fit sub element
  fit:StackFit.loose,//Minimum adaptation element
  //fit:StackFit.passthrough, / / directly pass the constraints of the Stack parent component to the child components

body: Center(
  child: Container(
    color: Colors.blue,
    child: Stack(
      fit: _isSelect ? StackFit.expand : StackFit.loose, 
      // fit: StackFit.loose, / / minimum fit
      // fit: StackFit.expand, / / maximum fit
      // alignment: Alignment.center,
      alignment: Alignment(-1, 0.75),
      children: [
        Text("Stack Factors affecting component size"),
        Positioned(
          left: 0,
          top: 0,
          child: FlutterLogo(
            size: 250,
          ),
        ),
        Positioned(
          left: 0,
          top: 0,
          child: Container(
            width: 24,
            height: 24,
            color: Colors.black,
          ),
        ),
        Switch(
          value: _isSelect,
          onChanged: (value) {
            setState(() {
              _isSelect = value;
            });
            print('Switch--------value:$value');
            print('Switch--------_isSelect:$_isSelect');
          },
        ),
      ],
    ),
  ),
),

Stack # excess display and cutting: Although the excess part can be displayed, it cannot respond to user click events

  1. overflow: Overflow.visible
  2. clipBehavior: Clip.none, / / although the excess part can be displayed, it cannot respond to the user's click event

 

body: Center(
  child: Container(
    color: Colors.blue,
    constraints: const BoxConstraints(
      maxWidth: 350,
      minWidth: 10,
      maxHeight: 350,
      minHeight: 10,
    ),
    child: Stack(
      //alignment: Alignment.bottomCenter,
      overflow: Overflow.visible,
      clipBehavior: Clip.none,//Although the excess part can be displayed, it cannot respond to user click events
      children: [
        FlutterLogo(size: 250),
        Positioned(
          left: 20,
          top: -20,
          width: 250,
          height: 50,
          child: Container(
            width: 24,
            height: 24,
            color: Colors.orange,
          ),
        ),
      ],
    ),
  ),
),

layout factors that determine the size of Container components

When the Container has no child components, its size occupies the maximum constraint of the parent component;
When the container has subcomponents, its size is the size of the subcomponents
*When the container has alignment attribute: the size of the container # itself occupies the maximum constraint of the parent component; (alignment attribute) similarly wraps a layer of layout
*When the parent component of container is an unbounded constraint such as Column/Row/ListView, unbolder cannot determine the maximum value of the constraint! At this time, Contaiber will take the minimum value of the constraint

When there are no sub components:

body: Center(
  child: Container(
    color: Colors.orange,
    // child: FlutterLogo(size: 100),
  ),
),

When there are subcomponents

body: Center(
  child: Container(
    color: Colors.orange,
    child: FlutterLogo(size: 100),
  ),
),

Right alignment attribute:

body: Container(
  alignment: Alignment.center,
  color: Colors.orange,
  child: const FlutterLogo(
    size: 50,
  ),
),

When Column/Row/ListView is an unbounded constraint:

body: Column(
  children: [
    Container(
      // alignment: Alignment.center,
      color: Colors.orange,
      child: const FlutterLogo(
        size: 50,
      ),
    )
  ],
),

Of course, you can also modify the constraints of the Container to change the constraints of the parent component to repair the maximum constraints of the parent component

body: Center(
  child: Container(
    constraints: const BoxConstraints(
      maxHeight: 250,
      minHeight: 10,
      maxWidth: 250,
      minWidth: 10,
    ),
    color: Colors.orange,
    // child: FlutterLogo(size: 30),
  ),
),

If there is a , constraint transfer / multi-component constraint superposition , the intersection of , constraints is taken

The Center component is a loose constraint range: width: 0 to screen width; height: 0 to screen height
SizedBox force the width to 200; Height has no effect
Container: constrained by parent component, height 200, affected by child component, width 100
Fluterlog: 100 wide and 100 high;
So here, the size of the Container component is actually affected by the superposition of multiple components!

body: Center(
  //Loose constraint 0 - screen width and height
  child: SizedBox(
    width: 200, // Width tight constraint
    child: Container(
      //Page number superposition: the width is determined by SizeBox, because the height of the Container sub component is 200 * 100 of the height of the sub component
      color: Colors.orange,
      child: FlutterLogo(size: 100), //Tight sub assembly 100 *
    ),
  ),
),

In essence: the Container component class is written in a syntax; Many of the attributes are implemented one by one: and so on

If there is an alignment attribute, it will wrap a layer of Align(alignment: alignment!, child: current);
If there is a color attribute, it will wrap a layer of ColoredBox(color: color!, child: current);
Part of his source code:
 

   @override
  Widget build(BuildContext context) {
    Widget? current = child;
 
    if (child == null && (constraints == null || !constraints!.isTight)) {
      current = LimitedBox(
        maxWidth: 0.0,
        maxHeight: 0.0,
        child: ConstrainedBox(constraints: const BoxConstraints.expand()),
      );
    }
 
    if (alignment != null)
      current = Align(alignment: alignment!, child: current);
 
    final EdgeInsetsGeometry? effectivePadding = _paddingIncludingDecoration;
    if (effectivePadding != null)
      current = Padding(padding: effectivePadding, child: current);
 
    if (color != null)
      current = ColoredBox(color: color!, child: current);
 
    if (clipBehavior != Clip.none) {
      assert(decoration != null);
      current = ClipPath(
        clipper: _DecorationClipper(
          textDirection: Directionality.maybeOf(context),
          decoration: decoration!,
        ),
        clipBehavior: clipBehavior,
        child: current,
      );
    }
 
    if (decoration != null)
      current = DecoratedBox(decoration: decoration!, child: current);
 
    if (foregroundDecoration != null) {
      current = DecoratedBox(
        decoration: foregroundDecoration!,
        position: DecorationPosition.foreground,
        child: current,
      );
    }
 
    if (constraints != null)
      current = ConstrainedBox(constraints: constraints!, child: current);
 
    if (margin != null)
      current = Padding(padding: margin!, child: current);
 
    if (transform != null)
      current = Transform(transform: transform!, alignment: transformAlignment, child: current);
 
    return current!;
  }

Keywords: Flutter

Added by crunchyfroggie on Tue, 08 Mar 2022 10:08:29 +0200