当我将ListView
包裹在FutureBuilder
中以便拥有简单的Column
时,我想在另一个小部件中包含Row
。我收到此错误:
The following assertion was thrown during performLayout():
I/flutter (13816): RenderFlex children have non-zero flex but incoming height constraints are unbounded.
I/flutter (13816): When a column is in a parent that does not provide a finite height constraint, for example if it is
I/flutter (13816): in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a
I/flutter (13816): flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining
I/flutter (13816): space in the vertical direction.
I/flutter (13816): These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child
I/flutter (13816): cannot simultaneously expand to fit its parent.
I/flutter (13816): Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible
I/flutter (13816): children (using Flexible rather than Expanded). This will allow the flexible children to size
I/flutter (13816): themselves to less than the infinite remaining space they would otherwise be forced to take, and
I/flutter (13816): then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum
I/flutter (13816): constraints provided by the parent.
I/flutter (13816): If this message did not help you determine the problem, consider using debugDumpRenderTree():
我的代码:
class ActivityShowTicketReplies extends StatefulWidget {
final Map<String, dynamic> ticketData;
ActivityShowTicketReplies({@required this.ticketData});
@override
State<StatefulWidget> createState() => ActivityShowTicketRepliesState();
}
class ActivityShowTicketRepliesState extends State<ActivityShowTicketReplies> {
TicketsTableData get _ticket => TicketsTableData.fromJson(json.decode(widget.ticketData.values.toList()[0][0].toString()));
@override
Widget build(BuildContext context) {
return ScopedModel(
model: CounterModel(),
child: Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
body: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: RaisedButton(
color: Colors.indigo,
onPressed: () => BlocProvider.of<AppPagesBloc>(context).dispatch(FragmentNavigateEvent(routeName: FRAGMENT_NEW_TICKET)),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.0)),
child: Container(
child: Text(
'new ticket',
style: AppTheme(context).caption().copyWith(color: Colors.white),
),
),
),
),
],
),
FutureBuilder(
future: Provider.of<TicketRepliesTableDao>(context).find(ticketId: _ticket.id),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
final List<TicketRepliesTableData> ticketReplies = snapshot.data;
if (ticketReplies.isNotEmpty) {
return Column(
children: <Widget>[
Card(
clipBehavior: Clip.antiAlias,
color: Colors.grey[50],
margin: EdgeInsets.all(10.0),
child: InkWell(
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: ListTile(
title: Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: Text(
'subject',
style: AppTheme(context).caption().copyWith(fontFamily: 'ShabnamBold'),
),
),
subtitle: Text(
_ticket.subject,
style: AppTheme(context).caption(),
),
),
),
Container(
height: 30.0,
margin: EdgeInsets.zero,
width: double.infinity,
color: Colors.grey[200],
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
],
),
),
],
),
Align(
alignment: Alignment.topLeft,
child: Container(
margin: EdgeInsets.only(top: 10.0),
constraints: BoxConstraints(
minWidth: 70.0,
),
height: 20.0,
width: 70.0,
decoration: BoxDecoration(
color: Colors.green[200],
borderRadius: BorderRadius.only(
topRight: Radius.circular(5.0),
bottomRight: Radius.circular(5.0),
)),
child: Center(
child: Text(
'status',
style: AppTheme(context).overLine().copyWith(fontFamily: 'ShabnamBold', color: Colors.black),
),
)),
),
],
),
onTap: () {},
),
),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
clipBehavior: Clip.antiAlias,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(
ticketReplies[index].createdAt,
style: AppTheme(context).caption().copyWith(fontFamily: 'ShabnamLight'),
),
],
),
ListTile(
title: Text(ticketReplies[index].reply),
),
],
),
),
);
},
itemCount: ticketReplies.length,
),
),
],
);
} else {
return Center(
child: Text(
'there isn't any reply message',
style: AppTheme(context).caption(),
),
);
}
} else {
return _loader(context, 'no reply');
}
} else
return _loader(context, Strings.pleaseWait);
},
),
],
),
),
),
);
}
Widget _loader(BuildContext context,String message) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ColorLoader3(
radius: 25.0,
dotRadius: 5.0,
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Text(
Strings.pleaseWait,
style: AppTheme(context).caption().copyWith(color: Colors.red[900]),
),
),
],
));
}
}
答案 0 :(得分:25)
用另一个 Column > Expanded
包装一个 Expanded
如何解决错误。
出现 "RenderFlex children have non-zero flex but incoming height constraints are unbounded"
错误的常见嵌套 Column-Expanded 层次结构:
Screen
→ Column
→ Column
→ Expanded → ERROR
发生了什么:
Screen
↓ constraint ↓ (Screen)
Column
Text_A (fixed height: no constraint needed) → OK
Column
↓ constraint ↓ (unbounded)
Text_B (fixed height) → OK
Expanded: calc. height = unbounded - Text_B → ERROR
在布局期间,Column
执行(按顺序):
Text_A
是固定高度的。它不使用传入约束进行布局。
Expanded
不过,是一个 flex-factor 小部件,在布局固定大小的项目后,在 剩余 空间上调整自身大小。这需要传入约束(父大小)进行减法:
parent size (constraint) - fixed-items size = remaining space
第一个 Column
从设备屏幕获取约束(通过 Scaffold
等提供)。
但是,第二个 Column
(嵌套的)位于无界空间中。
无法计算剩余空间:
unbounded - Text_B = unbounded (error)
Column
是无界的?Screen
→ Column
→ Column
→ Expanded
复制自 Column
SDK 源文档,第 1 步:
/// 1. Layout each child with a null or zero flex factor (e.g., those that are not
/// [Expanded]) with unbounded vertical constraints
第二个,嵌套的 Column
:
Column
的孩子(显然是第一个),并且...第二点很容易被忽略/看不到,但 Column
不是一个弹性因子小部件。
正在检查 SDK 源...
Column
扩展了 Flex
类。
Flex
,不 是否有 flex
字段/弹性系数。只有 Flexible
类及其子类是弹性因子小部件。
所以第二个 Column
被放置在无界约束中,因为它不是一个 flex-factor 小部件。这些无界约束用于布局 Text_B
小部件(固定大小或空弹性系数小部件),然后 Expanded
尝试计算剩余空间。尝试使用无界约束计算剩余空间时....
unbounded - Text_B = unbounded (error)
? Expanded
爆炸?
Flexible
过度重复:Flexible
,是 带有 flex
字段的弹性系数小部件/因素。
Expanded
和 Spacer
是 Flexible
的唯一子类(我知道)。
所以 Expanded
、Spacer
和 Flexible
是唯一的 flex-factor 小部件和
Flexible != Flex
修复小部件树:
Screen
→ Column
→ Expanded ← new
→ Column
→ Expanded → OK
为什么会这样...
Screen
↓ constraint ↓
Column
Text_A ↑ fixed-size ↑
↓ constraint ↓ (calculated: Screen height - Text_A height)
Expanded_A
↓ constraint ↓ (Screen - Text_A)
Column
Text_B ↑ fixed-size ↑
Expanded_B: calc. height = (Screen - Text_A) - Text_B = remaining space → OK
在这种情况下...
固定项布置后(Text_A
),计算剩余空间Expanded_A
:
parent size (screen) - fixed-items (Text_A) = remaining space
现在 Expanded_A
具有定义的空间量。
Expanded_A
提供它的大小,供子 Column
在布局 Expanded_B
后计算 Text_B
的剩余空间使用。
parent size - fixed-items = remaining space
↓
(Screen - Text_A) - (Text_B) = remaining space for Expanded_B
现在所有 flex-factor 相对大小的小部件(即 Expanded_A
、Expanded_B
)都有用于计算其布局大小的有界约束。
请注意,您可以在此处将 Flexible
与 Expanded
互换使用。它以与 Expanded
相同的方式计算剩余空间。它只是不会强迫孩子适应它的大小,所以如果他们愿意,他们可以更小。
/// Unbounded constraint: NOT OK
class RenderFlexUnboundedPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Column(
children: [
Text('Column > Column > Text_A'),
Expanded(
child: Text('Column > Column > Expanded_A')) // explosions
],
)
],
),
);
}
}
/// Constraints provided: OK
class RenderFlexPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text('Column > Text_A'),
Expanded( // Expanded_A
child: Column(
children: [
Text('Column > Expanded_A > Column > Text_B'),
Expanded( // Expanded_B
child: Text('Column > Expanded_A > Column > Expanded_B'))
],
),
)
],
),
);
}
}
答案 1 :(得分:2)
在此代码中。
const request = require('request')
const fs = require('fs')
const chalk = require('chalk')
var windowSlider = 200
var totlExtractedRecords = 0;
fs.writeFileSync('output.txt', '')
const option = {
url: 'https://jira.yourdomain.com/rest/api/2/search',
json: true,
qs: {
jql: "project in (xyz)",
maxResults: 200,
startAt: 0,
}
}
const callback = (error, response) => {
const body = response.body
console.log(response.body)
const dataArray = body.issues
const total = body.total
totlExtractedRecords = dataArray.length + totlExtractedRecords
if (totlExtractedRecords > 0) {
option.qs.startAt = windowSlider + option.qs.startAt
}
dataArray.forEach(element => {
fs.appendFileSync('output.txt', element.key + '\n')
})
console.log(chalk.red.inverse('Total extracted data : ' + totlExtractedRecords))
console.log(chalk.red.inverse('Total data: ' + total))
if (totlExtractedRecords < total) {
console.log('Re - Running with start as ' + option.qs.startAt)
console.log('Re - Running with maxResult as ' + option.qs.maxResults)
request(option, callback).auth('api-reader', 'APITOKEN', true)
}
}
request(option, callback).auth('api-reader', 'APITOKEN', true)
您需要使用if (ticketReplies.isNotEmpty) {
return Column(...);
}
或SizedBox
,例如:
Expanded
答案 2 :(得分:2)
尝试将Column
或Expanded
或Flexible
中的其他任何小工具包装起来,即可完成。
别忘了给Scrolling widgets
此问题的解决方法是将Column
小部件包装在Expanded
小部件内。下面的示例。
Expanded(
child: Column(
children: <Widget>[
Container(
height: 400,
width: 400,
child: ListView.builder(
itemCount: 2,
itemBuilder: (context, position) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text("e.g., those that are not Expanded"),
),
);
},
),
),
],
),
)
要了解更多信息,请参见:“RenderFlex children have non-zero flex…”
答案 3 :(得分:2)
我想提供另一个解决方案,因为我必须自己解决这个问题。对于上下文,这是引发此错误的小部件的过度简化结构:
Container
child: Column
children: Column, Spacer, Row
就我而言,我希望 Container
扩展其内部的内容。最初,我为这个容器定义了高度和宽度,但因为我希望它动态扩展,所以我删除了这些约束。然后引发了错误:
“RenderFlex 子级具有非零 flex 但传入的高度约束是无界的”
我的问题是行之间的 Spacer
。第一个 Column
的孩子试图无限扩展(因此是“非零弹性”),因为 Spacer
将每个孩子推到其父母的垂直边界。这通常不是问题,但是对于间隔器将子级推向父级没有限制。这是因为它们的父级(第一个 Column
)也在尝试扩展,因为 Container
没有被赋予高度或宽度属性。
我的解决方法是简单地将 Spacer
替换为具有有限高度的 SizedBox
:
Container
child: Column
children: Column, SizedBox(height: 10), Row
答案 4 :(得分:0)
这种方法永远不会让我失望:
Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus finibus luctus tortor id pulvinar. Donec sollicitudin, dui vitae aliquam tristique, eros risus commodo enim, eget lobortis arcu velit ac arcu. "),
Text("Nunc tristique, ex ut volutpat feugiat, nulla nibh iaculis lectus, laoreet auctor justo tellus quis mi. Praesent ut interdum sem. Donec eget finibus augue, et vehicula elit. Praesent eu euismod arcu, eu maximus tellus. Ut diam est, sodales nec enim a, pharetra lobortis erat."),
]
)
)
答案 5 :(得分:0)
如果您想解决 Render Flex
问题,请尝试:
Scaffold(
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
答案 6 :(得分:0)
就我而言,这是因为我没有使用 Expanded
小部件。然而,这也无助于实现结果。相反,我将 SizedBox
与 height
属性一起使用,如下所示:
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
这很容易解决了我的问题。