Flutter 布局:如何在 Flutter 中将一行放入 Flex(或另一行)中?还使用 Stack 小部件

Flutter Layout: How can I put a Row inside a Flex (or another Row) in Flutter? Also using Stack widget

我需要将 2 个组合小部件合二为一 Row:

组合的小部件名为“boxText”。我需要它两次,每次都在一个带有两个 Texts 和一个 TextFormField 的边框内,例如:

Stack
  Image and others
  Form
    Row or Flex or Whatever:
    +------------------------------+    +------------------------------+
    | Text  Text TextFormField     |    | Text Text  TextFormField     |
    +------------------------------+    +------------------------------+

我的代码(和眼泪): 重要提示:仅当添加 TextFormField 时才会发生异常。

@override
Widget build(BuildContext context) {
// Composed Widget
 Widget boxText = new Container(
  decoration: new BoxDecoration(
    border: new Border.all(
      color: Colors.cyan[100],
      width: 3.0,
      style: BorderStyle.solid,
    ),
  ),
  margin: new EdgeInsets.all(5.0),
  padding: new EdgeInsets.all(8.0),
  child: new Row(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      new Text(
        'Text',
        style: null,
      ),
      new Text(
        'Text',
        style: null,
      ),
      new TextFormField(
        decoration: const InputDecoration(
          hintText: '',
          labelText: 'label',
        ),
        obscureText: true,
      ),
    ],
  ),
);

return new Scaffold(
  key: _scaffoldKey,
  body: new Stack(
    alignment: AlignmentDirectional.topStart,
    textDirection: TextDirection.ltr,
    fit: StackFit.loose,
    overflow: Overflow.clip,
    children: <Widget>[

      new Container(
        color: Colors.red[200],
        margin: new EdgeInsets.only(
          left: MediaQuery.of(context).size.width * 0.05,
          right: MediaQuery.of(context).size.width * 0.05,
          top: MediaQuery.of(context).size.height * 0.4,
          bottom: MediaQuery.of(context).size.height * 0.1,
        ),
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: new Form(
          key: _formKey,
          child: new ListView(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            children: <Widget>[
              new Flex(
                direction: Axis.horizontal,
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  boxText,
                  boxText,
                ],
              ),
            ],
          ),
        ),
      ),
    ],
  ),
    );
  }

如果可能的话,如何使这些小部件在没有以下情况的情况下工作:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞══

The following assertion was thrown during performLayout():

An InputDecorator, which is typically created by a TextField, cannot 
have an unbounded width.

This happens when the parent widget does not provide a finite width 
constraint. For example, if the InputDecorator is contained by a Row, 
then its width must be constrained. An Expanded widget or a SizedBox 
can be used to constrain the width of the InputDecorator or the 
TextField that contains it.

'package:flutter/src/material/input_decorator.dart':

Failed assertion: line 945 pos 7: 'layoutConstraints.maxWidth < 
double.infinity'

将您的 ContainerTextFormField 都包裹在 Flexible 小部件中。

Widget boxText = new Flexible(child: new Container(
      decoration: new BoxDecoration(
        border: new Border.all(
          color: Colors.cyan[100],
          width: 3.0,
          style: BorderStyle.solid,
        ),
      ),
      margin: new EdgeInsets.all(5.0),
      padding: new EdgeInsets.all(8.0),
      child: new Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[

          new Text(
            'Text',
            style: null,
          ),
          new Text(
            'Text',
            style: null,
          ),
          new Flexible (child: new TextFormField(
            decoration: const InputDecoration(
              hintText: '',
              labelText: 'label',
            ),
            obscureText: true,
          ),),
        ],
      ),
    ));

问题是您的 Container 依赖其 parent 来决定其宽度。因为没有parent,所以无限宽

要解决这个问题,给它一个 parent 告诉它 child 如何处理宽度。 Flexible 或 Expanded 可以做到这一点。 Expanded 告诉它的 child 尽可能大(扩展),Flexible 告诉它的 child 尽可能小(收缩)。

我觉得 Expanded 是你最好的选择:

更改您的代码:

// Composed Widget
Widget boxText = new Container(
  decoration: new BoxDecoration(
  // all your other code here
);

// Composed Widget
Widget boxText = Expanded(   // <-- Add this Expanded widget
  child: new Container(
    decoration: new BoxDecoration(
    // all your other code here
  ),
);
         child: Row(
                children: <Widget>[
                  Expanded(
                    child: TextField(

                      decoration: InputDecoration(hintText: "text"),
                    ),
                  ),
                  Text("unit"),
                ],
              )),

RowColumn 固定大小的第一个布局小部件。固定大小的小部件被认为是不灵活的,因为它们在布局后无法自行调整大小。

flex 将自己与其他 flex 属性进行比较,然后确定每个灵活小部件收到的总剩余 space 的比例。

flex 属性相互比较时,它们的 flex 值之间的比率决定了每个 Flexible 小部件接收的总剩余 space 的比例。

remainingSpace * (flex / totalOfAllFlexValues)

在此示例中,flex 值的总和 (2) 确定两个 Flexible 小部件接收剩余总数的一半 space。 BlueBox 小部件(或固定大小的小部件)保持相同大小。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        BlueBox(),
        Flexible(
          fit: FlexFit.tight,
          flex: 1,
          child: BlueBox(),
        ),
        Flexible(
          fit: FlexFit.tight,
          flex: 1,
          child: BlueBox(),
        ),
      ],
    );
  }
}

class BlueBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(),
      ),
    );
  }
}