如何根据父级的大小布局小部件?

How can I layout widgets based on the size of the parent?

假设您有一个可能具有可变大小的父窗口小部件。

例如:

var container = new Container(
   height: 200.0, // Imagine this might change
   width: 200.0, // Imagine this might change
   // Imagine content in this container will 
   // depend on the parent container
   child: new Container(), 
);

也许您想让父容器的子容器根据给定的大小呈现不同的东西。

想想响应式设计断点,如果宽度超过X就用这个布局,如果宽度小于X就用那个布局。

在 Flutter 中执行此操作的最佳方法是什么?

您需要使用 LayoutBuilder 小部件,它将在布局时构建 并提供父小部件的约束。

LayoutBuilder 接受一个 build() 函数,该函数具有标准 BuildContext along with the BoxConstraints 作为参数,可用于帮助根据大小动态呈现小部件。

让我们构建一个简单的小部件示例,如果父级宽度大于 200px,则呈现 "LARGE",如果父级宽度小于或等于 200px,则呈现 "SMALL"。

var container = new Container(
  // Toggling width from 100 to 300 will change what is rendered
  // in the child container
  width: 100.0,
  // width: 300.0
  child: new LayoutBuilder(
    builder: (BuildContext context, BoxConstraints constraints) {
      if(constraints.maxWidth > 200.0) {
        return new Text('BIG');
      } else {
        return new Text('SMALL');
      }
    }
  ),
);

所以我遇到了一个有趣的情况,我的 parent child 根据内容(包含描述的文本)动态增加大小。此 parent 小部件以只读模式显示内容,但此解决方案还可以解决其他问题以及动态增加文本字段高度的问题。

我有一个 height variableGlobalKey。在 initState 的小部件中,我正在使用 SchedulerBinding,它在构建布局后运行 addPostFrameCallback

globalKey 被分配给我们需要的高度为 children 的任何 parent 小部件。

double height = 0.0;
GlobalKey _globalKey = GlobalKey();

  @override
  void initState() {
    SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
      height = _globalKey.currentContext.size.height;
      print('the new height is $height');
      setState(() {});
    });
    super.initState();
  }

其余代码如下所示

// this parent having dynamic height based on content 
Container(
  width: 100.0,
  key: _globalKey,
  child: Container(
    width: 100.0,
    child: Row(children: [  ///  you can have column as well or any other widget. 
      Container(child: ...),
      Container(height: height,), ///this widget will take height from parent 
    ],),
  )
)

要根据父级动态设置小部件大小,请使用以下代码:

Container(
  color: Colors.red,
  alignment: Alignment.center,
  child: Wrap(children: <Widget>[

    GestureDetector(
      child: Text(
        'Button',
        style: TextStyle(
            color: Color(0xff0079BF), fontSize:20),
      ),
      onTap: () {


        Navigator.pushReplacementNamed(context, '/signin');
      },
    ),


    Text(
      'You have pushed the button this many times:',
      style: TextStyle(fontSize: 50),
    ),

  ]),
)

希望这些解决方案对您有用。

您可以试试 IntrinsicHeight 小部件:

https://api.flutter.dev/flutter/widgets/IntrinsicHeight-class.html

对我来说,这是最简单的解决方案。但是好像很贵,所以还是尽量避免吧

var container = Container(
height: 200.0, // Imagine this might change
width: 200.0, // Imagine this might change

child: IntrinsicHeight(
      child: Container()), 
);

将小部件放入容器中并将其宽度 and/or 高度设置为 double.maxFinite

示例:

 child: Container(
     width: double.maxFinite,
   )