Constraints - wurzelsand/flutter-memos GitHub Wiki

Constraints

Ich erwarte ein 300x400 großes gelbes Rechteck und darin ein 100x100 großes rotes Quadrat:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
        home: Scaffold(
            body: Container(
                width: 300,
                height: 400,
                color: Colors.yellow,
                child: const ExampleWidget()))),
  );
}

class ExampleWidget extends StatelessWidget {
  const ExampleWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: Colors.red,
    );
  }
}

Stattdessen:

Wie bekomme ich nun das gewünschte Ergebnis?

Ausführung

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
        home: Scaffold(
            body: Container(
                width: 300,
                height: 400,
                color: Colors.yellow,
                child: const ExampleWidget()))),
  );
}

class ExampleWidget extends StatelessWidget {
  const ExampleWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        width: 100,
        height: 100,
        color: Colors.red,
      ),
    );
  }
}

Bemerkungen

  • Es gibt Parent-Widgets, wie z.B. Scaffold, Align, Row, Column oder Center, die lassen ihr Child entscheiden, wie groß es (das Child) ist. Andere Parent-Widgets, wie z.B. Container, zwingen ihre Childs gleich groß wie sie selbst zu sein.

Combined Constraints

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Center(
            child: Container(
                color: Colors.red,
                constraints: const BoxConstraints(
                    minWidth: 100,
                    maxWidth: 200,
                    minHeight: 200,
                    maxHeight: 300),
                child:
                    Container(color: Colors.green, width: 1, height: 1000))));
  }
}

Notes

The size of the Center widget is limited by the screen to its (the screens) size. Center therefore fills the entire screen. Center, in turn, gives its child (a red Container in this case) a free hand in choosing its size. It wants to be between 100 and 200 logical pixels wide and between 200 and 300 logical pixels high. If the Container had no child, it would choose the highest values, so it would be 200x300 pixels. But the Container has another container as a child (a green Container in this case), which would like to be 1 pixel wide and 1000 pixels high. A Container does not let its child choose its size, but restricts it:

  • If the width of the child is smaller than minWidth, the new width is minWidth.
  • If the width of the child is between minWidth and maxWidth, the width of the child remains unchanged.
  • If the width of the child is greater than maxWidth, the new width is maxWidth.

The same rules apply to the height. So the green Container is 100x300 pixels. Since a Container is always as large as its child, the red Container is also 100x300 pixels. It is hidden here by its child.

ConstrainedBox

You might now expect a 10x50 red rectangle on a 300x400 yellow rectangle:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
        home: Scaffold(
            body: Container(
                width: 300,
                height: 400,
                color: Colors.yellow,
                child: const ExampleWidget()))),
  );
}

class ExampleWidget extends StatelessWidget {
  const ExampleWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return ConstrainedBox(
      constraints: const BoxConstraints(maxWidth: 10, maxHeight: 50),
      child: Container(
        width: 100,
        height: 100,
        color: Colors.red,
      ),
    );
  }
}

Instead:

Notes

Scaffold is as big as the screen, but lets its body widget decide how big it wants to be: a yellow 300x400 Container. The Container has a child: ConstrainedBox. This must be exactly the same size as its parent. Its constraints are therefore adjusted and are now 300x400. And also it transfers its constraints to its child, which actually wants to be 100x100 large but is now also 300x400 large. One solution could be:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
        home: Scaffold(
            body: Container(
                width: 300,
                height: 400,
                color: Colors.yellow,
                child: const ExampleWidget()))),
  );
}

class ExampleWidget extends StatelessWidget {
  const ExampleWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.bottomCenter,
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 10, maxHeight: 50),
        child: Container(
          width: 100,
          height: 100,
          color: Colors.red,
        ),
      ),
    );
  }
}