Flutter - Using IntrinsicWidth Widget Examples

This tutorial explains what is IntrinsicWidth widget in Flutter along with the usage examples.

IntrinsicWidth is a widget used to size its child to its maximum intrinsic width. It can be useful if the available width is unlimited, but you want to set the size of a widget to its intrinsic width.

Using IntrinsicWidth

Let's start with an example where there is a Column widget with the crossAxisAlignment sets to stretch. It has two Container widgets as its children with the second container is wrapped as the child of an Expanded widget. That means the height of the second container will be expanded to the maximum space. For the width of the Column, because it uses CrossAxisAlignment.stretch, it will also be expanded to the maximum space.

  Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Container(
        width: 200,
        height: 100,
        color: Colors.teal,
      ),
      Expanded(
        child: Container(
          width: 100,
          height: 100,
          color: Colors.red,
        ),
      ),
    ],
  )

Output:

Flutter - Without IntrinsicWidth

What if you want to set the width of a widget to be its intrinsic width. You can wrap it as the child of an IntrinsicWidth widget. Below is the constructor.

  IntrinsicWidth({ Key key, this.stepWidth, this.stepHeight, Widget child })

Here's a basic usage example which only passes the child argument.

  IntrinsicWidth(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Container(
          width: 200,
          height: 100,
          color: Colors.teal,
        ),
        Expanded(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ],
    ),
  )

Output:

Flutter - IntrinsicWidth

The above output shows that the width is set to the width of the children with maximum width which is the first Container whose width is 200.

In the next example, we are going to set the stepWidth argument to 150. That causes the width of the child to be the smallest value which is a multiple of 150.

  IntrinsicWidth(
    stepWidth: 150,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Container(
          width: 200,
          height: 100,
          color: Colors.teal,
        ),
        Expanded(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ],
    ),
  )

Output:

Flutter - IntrinsicWidth - stepWidth 150

Next, we are going to set the stepHeight argument to 100. In the previous examples where the stepHeight is not passed, the height of the child expands to fill the maximum space. By passing stepWidth argument, the height of the child will be set to a minimum value that's a multiplication of the stepHeight.

  IntrinsicWidth(
    stepHeight: 100,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Container(
          width: 200,
          height: 100,
          color: Colors.teal,
        ),
        Expanded(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ],
    ),
  )

Output:

Flutter - IntrinsicWidth - stepHeight 100

Using IntrinsicWidth is considered expensive because of the need to add a speculative layout pass before the final layout phase. In the worst case, the depth of the tree can be O(N²). Therefore, the usage of IntrinsicWidth should be avoided if possible. For the above cases, you can consider using a widget that can be used to add constraints to the child, such as SizedBox or ConstrainedBox.

  SizedBox(
    width: 300,
    height: 200,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Container(
          width: 200,
          height: 100,
          color: Colors.teal,
        ),
        Expanded(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ],
    ),
  )

Output:

Flutter - Column with SizedBox

Keep in mind that the constraints applied by IntrinsicWidth widget must comply with the constraints from the parent. Therefore, the child's width can be less than its intrinsic width if the maximum width constraint from the parent is not large enough. Likewise, the child's width can be larger than its intrinsic width if the minimum width constraint is larger than the intrinsic width.

IntrinsicWidth Parameters

  • Key key: The widget's key.
  • Widget child: The widget under this widget in tree, whose width will be set to its intrinsic width.
  • double stepWidth: If non-null, force the width of the child to be multiple of this value. If null or 0.0, the width of the child is the same as its maximum intrinsic width.
  • double stepHeight: If non-null, force the height of the child to be multiple of this value. If null or 0.0, the height of the child will not be constrained.

Full Code

  import 'package:flutter/material.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
  
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: _IntrinsicWidthExample(),
      );
    }
  }
  
  class _IntrinsicWidthExample extends StatelessWidget {
  
    final Widget column = Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Container(
          width: 200,
          height: 100,
          color: Colors.teal,
        ),
        Expanded(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ],
    );
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: const Text('Woolha.com Flutter Tutorial'),
        ),
  //      body: column,
        body: IntrinsicWidth(
          stepWidth: 150,
          stepHeight: 100,
          child: column,
        ),
  //      body: SizedBox(
  //        width: 300,
  //        height: 200,
  //        child: column,
  //      ),
      );
    }
  }

Summary

That's how to use IntrinsicWidth in Flutter which is used to set the width of a widget to its intrinsic width. You can also pass stepWidth and/or stepHeight arguments to force the width and/or the height of the child to be a multiplication of the given values.

You can also read about:

  • IntrinsicHeight: a widget used to set the height of its child to the child's intrinsic height.
  • UnconstrainedBox: a widget that imposes no constraints on its child.
  • ConstrainedBox: a widget that imposes additional constraints on its child.
  • SizedBox: a box with a specified size.