【问题标题】:How can I layout widgets based on the size of the parent?如何根据父级的大小布局小部件?
【发布时间】:2017-05-24 07:48:05
【问题描述】:

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

例如:

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 中最好的方法是什么?

【问题讨论】:

标签: flutter dart flutter-layout flutter-widget


【解决方案1】:

您将希望使用 LayoutBuilder 小部件,该小部件将在布局时构建并提供父小部件的约束。

LayoutBuilder 接受 build() 函数,该函数具有标准的 BuildContextBoxConstraints 作为参数,可用于帮助根据大小动态呈现小部件。

让我们构建一个简单的小部件示例,如果父宽度大于 200 像素,则呈现“大”,如果父宽度小于或等于该宽度,则呈现“小”。

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');
      }
    }
  ),
);

【讨论】:

  • 谢谢,我一直在努力根据父小部件的大小来布局一个小部件,首先我尝试使用屏幕高度减去应用栏高度和底栏高度,这很愚蠢而不是在所有实体手机上工作。
  • 如果小部件需要宽度和高度怎么办?如何将其设置为父母的大小?
  • 这很好,除了约束与大小不同。当您尝试在Scrollable 中获取小部件的大小时,这一点变得很明显。如果您有一个 ListView 并且您尝试获取它的一个孩子的垂直约束,它会给您一个 double.infinity 的 maxHeight 和一个 0.0 的 minHeight
  • 呃!非常感谢
【解决方案2】:

想要一个容器以它的百分比占用部分可用空间(意味着一半的父窗口小部件等......)?然后使用FractionallySizedBox

相对于其父级调整小部件的大小

FractionallySizedBox 是一个小部件(container),它允许其子级拥有widthFactorheightFactor。您可以将其视为一种比例值。因此,如果我们想要一个容器占用一半可用空间horizontallyvertically,我们将执行以下操作:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FractionallySizedBox"),
      ),
      body: FractionallySizedBox(
        widthFactor: 0.5,
        heightFactor: 0.5,
        child: Container(
          // this container won't be larger than
          // half of its parent size
        ),
      ),
    );
  }

将其子级大小调整为总可用空间的一小部分的小部件。更多布局算法详情见RenderFractionallySizedOverflowBox.

【讨论】:

    【解决方案3】:

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

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

    globalKey 被分配给我们需要它的孩子高度的任何父窗口小部件。

    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 
        ],),
      )
    )
    

    【讨论】:

    • 如果我有很多消息气泡而不是只有一个,你知道我该如何使用它吗?
    • @scottlee 有趣的问题,我现在已经在研究它了 :) 。我需要那个用于cmets。我想解决方案是将气泡作为单独的小部件并使用 StreamBuilder 会有所帮助。一旦您知道小部件的构建完成,您就可以通过 StreamBuilder 将该高度发送到特定的小部件。我相信这会有所帮助。
    • @scottlee 所以我试了一下,效果很好。让我知道你的工作情况,我可能会为你提供解决方案。
    【解决方案4】:

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

    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),
        ),
    
      ]),
    )
    

    我希望这个解决方案对你有用。

    【讨论】:

      【解决方案5】:

      你可以试试 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()), 
      );
      

      【讨论】:

        【解决方案6】:

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

        例子:

         child: Container(
             width: double.maxFinite,
           )
        

        【讨论】:

          猜你喜欢
          • 2019-10-11
          • 2020-05-12
          • 2014-12-29
          • 1970-01-01
          • 1970-01-01
          • 2014-07-14
          • 1970-01-01
          • 2012-05-31
          • 1970-01-01
          相关资源
          最近更新 更多