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'
将您的 Container
和 TextFormField
都包裹在 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"),
],
)),
Row
和 Column
固定大小的第一个布局小部件。固定大小的小部件被认为是不灵活的,因为它们在布局后无法自行调整大小。
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(),
),
);
}
}
我需要将 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'
将您的 Container
和 TextFormField
都包裹在 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"),
],
)),
Row
和 Column
固定大小的第一个布局小部件。固定大小的小部件被认为是不灵活的,因为它们在布局后无法自行调整大小。
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(),
),
);
}
}