行内的TextField导致布局异常:无法计算大小

我得到一个渲染异常,我不知道如何修复。我试图创建一个有3行的列。

行[图片]

行[TextField]

行(按钮)

下面是我构建容器的代码:

Container buildEnterAppContainer(BuildContext context) {
var container = new Container(
padding: const EdgeInsets.all(8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
buildImageRow(context),
buildAppEntryRow(context),
buildButtonRow(context)
],
),
);
return container;
}

以及文本容器的buildAppEntryRow代码

Widget buildAppEntryRow(BuildContext context) {
return new Row(
children: <Widget>[
new TextField(
decoration: const InputDecoration(helperText: "Enter App ID"),
style: Theme.of(context).textTheme.body1,
)
],
);
}

当我运行时,我得到以下异常:

I/flutter ( 7674): BoxConstraints forces an infinite width.
I/flutter ( 7674): These invalid constraints were provided to RenderStack's layout() function by the following
I/flutter ( 7674): function, which probably computed the invalid constraints in question:
I/flutter ( 7674):   RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:256:13)
I/flutter ( 7674): The offending constraints were:
I/flutter ( 7674):   BoxConstraints(w=Infinity, 0.0<=h<=Infinity)

如果我改变buildAppEntryRow只是一个TextField,而不是像这样

 Widget buildAppEntryRow2(BuildContext context) {
return new TextField(
decoration: const InputDecoration(helperText: "Enter App ID"),
style: Theme.of(context).textTheme.body1,
);
}

我不再得到异常。我在Row实现中遗漏了什么,导致它无法计算该行的大小?

135991 次浏览

(我假设你正在使用Row,因为你想在将来把其他小部件放在TextField旁边。)

Row小部件想要确定它的非柔性子对象的内在大小,以便它知道它为柔性子对象留下了多少空间。然而,TextField没有内在宽度;它只知道如何将自己的大小调整到父容器的完整宽度。尝试将它包装在FlexibleExpanded中,告诉Row你希望TextField占用剩余的空间:

      new Row(
children: <Widget>[
new Flexible(
child: new TextField(
decoration: const InputDecoration(helperText: "Enter App ID"),
style: Theme.of(context).textTheme.body1,
),
),
],
),

你应该使用Flexible来在一行中使用Textfield。

new Row(
children: <Widget>[
new Text("hi there"),
new Container(
child:new Flexible(
child: new TextField( ),
),//flexible
),//container




],//widget
),//row
一个简单的解决方案是将Text()包装在Container()中。 所以,你的代码将像这样:

Container(
child: TextField()
)

在这里,您还可以获得容器的宽度和高度属性,以调整文本字段的外观。如果你将文本字段包装在容器中,则不需要使用Flexible

正如@Asif Shiraz提到的,我也有同样的问题,并通过将列包裹在一个灵活的容器中解决了这个问题,就像这样,

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
body: Row(
children: <Widget>[
Flexible(
child: Column(
children: <Widget>[
Container(
child: TextField(),
)
//container
],
))
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
));
}
}
解决方案是将你的Text()包装在以下小部件之一: ExpandedFlexible。因此,使用Expanded的代码将像这样:

Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "Demo Text",
hintStyle: TextStyle(fontWeight: FontWeight.w300, color: Colors.red)
),
),
),

你会得到这个错误,因为TextField在水平方向上扩展,Row也是如此,所以我们需要限制TextField的宽度,有很多方法可以做到这一点。

  1. < p > Expanded使用

     Row(
    children: <Widget>[
    Expanded(child: TextField()),
    OtherWidget(),
    ],
    )
    
  2. Use Flexible

    Row(
    children: <Widget>[
    Flexible(child: TextField()),
    OtherWidget(),
    ],
    )
    
  3. Wrap it in Container or SizedBox and provide width

    Row(
    children: <Widget>[
    SizedBox(width: 100, child: TextField()),
    OtherWidget(),
    ],
    )
    

我也有同样的问题。

如果你愿意,你可以使用表格小部件来避免文本框的这种问题

Row(
children: [
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(left: 5.0,right: 5.0),
child: TextFormField(
controller: commentController,
validator: (String value){
if(value.isEmpty){
// ignore: missing_return
return 'Comment cannot be blank.';
}
},
decoration: InputDecoration(
labelText: "Comment",
labelStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.bold,
color: Colors.grey),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.green))),
),
),
),
],
),

如果你想让你的TextField根据它的内容水平调整大小,那么你可以用IntrinsicWidth小部件来包装它。

Row(
children: [
Text("From"),
SizedBox(width: 10,),
IntrinsicWidth(child: TextField(
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
hintText:  "Start Date Start Date Start Date",
hintStyle: TextStyle(color: Colour.pBlue, fontSize: 14),
border: InputBorder.none,
),
),),
SizedBox(width: 10,),
Text("To"),
SizedBox(width: 10,),
IntrinsicWidth(child:  IntrinsicWidth(child: TextField(
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
hintText:  "End Date",
hintStyle: TextStyle(color: Colour.pBlue, fontSize: 14),
border: InputBorder.none,
),
),)),
],
)

但在代码中使用它之前,请确保了解Flutter对这个小部件的描述。

创建一个小部件,将其子部件的大小设置为子部件的固有宽度。 这门课比较贵。

.

.

最好的解决方案是使用绝对空间值

        Row(
children: <Widget>[
SizedBox(
width: MediaQuery.of(context).size.width * 0.3,
child: _telephonePrefixInput()
),
SizedBox(width: MediaQuery.of(context).size.width * 0.02),
Expanded(child: _telephoneInput()),
],
),

当将TextFieldInputDecoration放在Row中时,会导致无限宽度的问题。Flutter在InputDecoration 约束属性文档中解释了这一点:

通常,decorator将填充给定的水平空间. ...如果为null,则将使用环境ThemeData.inputDecorationThemeInputDecorationTheme.constraints如果该值为空,则装饰器将填充可用宽度的默认高度基于文本大小。

因此,好消息是,TextField的宽度可以在不使用Expanded这样的周围小部件的情况下进行约束。简单地为TextField小部件使用的InputDecorationconstraints参数提供一个BoxConstraints的实例:

const TextField(
decoration: InputDecoration(
constraints: BoxConstraints.tightFor(
width: 200,
),
),
)

正如上面的Flutter文档中提到的,一组约束可以通过使用ThemeThemeData来一次应用到几个小部件上,ThemeThemeData指定了InputDecorationTheme,其中包含要继承和使用的Theme的后代小部件所需的约束。