为什么Container不尊重给出的大小?

时间:2019-12-27 11:10:40

标签: flutter dart

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: TestCode(),
    );
  }
}

class TestCode extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 200,
      height: 100,
      color: Colors.red,
      child: Container(
        width: 100,
        height: 100,
        color: Colors.green,
      ),
    );
  }
}

实际上,这段代码非常简单。我只想显示一个200 * 100的红色立方体和一个100 * 100的绿色立方体。

但是运行效果是全屏绿色?为什么会这样?

接下来,我在Scaffold上添加了TestCode,如下所示

@override
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Flutter Demo',
    home: Scaffold(body: TestCode()),
  );
}

效果似乎再次接近,显示出200 * 100的绿色长方体?为什么会这样?

接下来,我将对齐方式添加到第一个Container中,如下所示

@override
Widget build(BuildContext context) {
  return Container(
    alignment: Alignment.topLeft,
    width: 200,
    height: 100,
    color: Colors.red,
    child: Container(
      width: 100,
      height: 100,
      color: Colors.green,
    ),
  );
}

最后达到了预期的效果,为什么会这样,谁能解释,我必须弄清楚。

4 个答案:

答案 0 :(得分:0)

heightwidth属性将被覆盖。您可以在本文上获得有关框约束的更多信息: Dealing with box constraints

Flutter有layout widgets一堆可以完成工作。在您的情况下,您将Container赋予了home的{​​{1}}属性。这会将MaterialApp的最小尺寸设置为屏幕尺寸。 Container希望他的孩子填满整个屏幕,以防止出现黑色像素。这是预期的行为。但是,您可以使用可以打破此约束的布局小部件,它可以是MaterialAppCenter或其他。

FittedBox的示例:

FittedBox

输出:

enter image description here

答案 1 :(得分:0)

只需将您的代码更改为此。您必须指定对齐方式。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
  title: 'Flutter Demo',
  home: TestCode(),
  );
 }
}

class TestCode extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 200.0,
height: 100.0,
color: Colors.red,
alignment: Alignment.center, // where to position the child
child: Container(
  width: 100.0,
  height: 100.0,
  color: Colors.green,
   ),
  );
 }
}

答案 2 :(得分:0)

这是由我们在Flutter中所谓的“严格约束与宽松约束”引起的。

TD; DR,宽度/高度是严格的约束(在某种意义上,只有一种可能性)。

但是您从未向框架指定如何在父级指定的200x200的严格约束与子级100x100的严格约束之间进行切换。

这会导致约束冲突。这两个小部件都有一种可能性,没有任何一种可以使它们一起生活(像alignment)。

在这种情况下,父级的约束总会赢,因此我们最终得到一个200x200的正方形,子级填充了父级。


如果那不是您想要的东西,那么您应该将“紧”约束转换为“松”约束。

宽松约束是为孩子提供多种可能性的约束,通常可以消除冲突。

引入宽松约束的最常见方法是使用Alignment(或Centeralignment的{​​{1}}属性)。

这样,如果您写:

Container

然后在这种情况下,Container( width: 200, height: 100, color: Colors.red, child: Center( child: Container( width: 100, height: 100, color: Colors.green, ), ), ); 将充当父母与孩子Center之间的中间地带。

它将理解,两者都想要不同的大小。它将通过使孩子与父母对齐来解决冲突。


现在,您可能会问为什么要这样做?为什么Flutter不能在此处隐式添加路线?

那是因为在许多情况下,这种行为是所希望的

基本上,这可以确保始终有一种自定义对象大小的方法(而不必在所有小部件上公开大量属性)。

Container为例。它不会暴露任何改变其大小的内容,但我们可能希望它充满整个屏幕。

在这种情况下,我们会写:

RaisedButton

由于我们先前说明的行为,即在发生冲突时父级会覆盖子级大小,因此此代码将产生一个SizedBox.expand( child: RaisedButton(...), ) ,可以正确填充屏幕。

答案 3 :(得分:0)

请始终记住,默认情况下,容器采用父级的尺寸,这是将所有元素/小部件包装在根顶级容器中的一种好习惯,然后将每个容器包装在带有定位所需部件的小部件树中容器(中心可以是这样的小部件) 解决您的问题的简单方法是:

       // The root container
       Container(
          //Center for positioning the child Container properly
          child: Center(
            child: Container(
              height: 100,
              width: 200,
              color: Colors.red,
              //Center for positioning the child Container properly
              child: Center(
                child: Container(
                  height: 100,
                  width: 100,
                  color: Colors.green,
                ),
              ),
            ),
          ),
        ),