我的应用程序需要一个可以点击项目的水平列表视图。
粗略的布局描述如下
Container
|_ Stack
|_ (background content)
|_ Column (overlay, align end vertically)
|_ Expand (fill up space above)
|_ ListView (horizontal)
|_ SizedBox (padding)
问题
当插入这个 ListView(或取消注释)时,Flutter 抛出了以下错误:
======== Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
'package:flutter/src/rendering/viewport.dart': Failed assertion: line 1852 pos 16: 'constraints.hasBoundedHeight': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
The relevant error-causing widget was:
ListView file:///C:/Users/CybeX/CozyUp/cozyup-mobile-flutter/lib/ui/components/ui_component_partner_selector.dart:76:13
When the exception was thrown, this was the stack:
#2 RenderShrinkWrappingViewport.performLayout (package:flutter/src/rendering/viewport.dart:1852:16)
#3 RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
#4 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
#5 RenderObject.layout (package:flutter/src/rendering/object.dart:1777:7)
#6 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:113:14)
...
The following RenderObject was being processed when the exception was fired: RenderShrinkWrappingViewport#400d9 relayoutBoundary=up16 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... needs compositing
... parentData: <none> (can use size)
... constraints: BoxConstraints(0.0<=w<=395.4, 0.0<=h<=Infinity)
... size: MISSING
... axisDirection: right
... crossAxisDirection: down
... offset: ScrollPositionWithSingleContext#72596(offset: 0.0, range: null..null, viewport: null, ScrollableState, ClampingScrollPhysics -> RangeMaintainingScrollPhysics, IdleScrollActivity#601d0, ScrollDirection.idle)
RenderObject: RenderShrinkWrappingViewport#400d9 relayoutBoundary=up16 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
我尝试将 ListView
包裹在 Expanded
中,但这按照建议的 here 将其重新居中在屏幕中间。我尝试按照建议的 here 添加扩展顶部,但 Flutter 不喜欢这样。
fwiw,也尝试了 ShrinkWrap(在这里并没有真正期待太多 - 也没有帮助)
MVCE
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
List<String> imgSrc = [
"https://randomuser.me/api/portraits/women/84.jpg",
"https://randomuser.me/api/portraits/men/82.jpg",
"https://randomuser.me/api/portraits/women/11.jpg",
"https://randomuser.me/api/portraits/women/61.jpg",
"https://randomuser.me/api/portraits/men/1.jpg",
];
List<Widget> _listviewItems() {
return imgSrc
.map((e) => Image.network(e))
.map((e) => Image(
image: e.image,
fit: BoxFit.scaleDown,
width: 64,
))
.toList();
}
Widget w = Container(
child: Stack(
children: [
// Center(
// child: cards.first,
// ),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.all(0.0),
scrollDirection: Axis.horizontal,
children: _listviewItems(),
)),
SizedBox(
height: 8,
)
],
)
],
));
return Scaffold(
body: Container(width: double.infinity, child: w),
);
}
}
上图是用 ListView
包裹的 Expanded
,即
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: Container()
),
ListView(
padding: const EdgeInsets.all(0.0),
scrollDirection: Axis.horizontal,
children: _listviewItems(),
),
SizedBox(
height: 8,
)
],
)
问题:
如何将水平列表视图与屏幕底部对齐以允许水平滚动(如上图所示)?
仅供参考:我添加了 shrinkWrap: true
并将 Column
(在堆栈内)包裹在 Extended
(如建议的 here)中,导致错误引导我here,这表明相反 - 非常令人沮丧!
答案 0 :(得分:0)
用容器包裹你的列表视图,并像这样为容器提供高度
Container(
height:50,
ListView(
padding: const EdgeInsets.all(0.0),
scrollDirection: Axis.horizontal,
children: _listviewItems(),
),
),
答案 1 :(得分:0)
您可以在下面复制粘贴运行2完整代码
解决方案 1:您可以使用 bottomSheet
代码片段
return Scaffold(
appBar: ...
body: ...
bottomSheet: SizedBox(height: 64, child: listview()),
);
解决方案 2:用 ListView
和 Align
包裹 SizedBox
代码片段
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 64,
child: ListView(
padding: const EdgeInsets.all(0.0),
scrollDirection: Axis.horizontal,
children: _listviewItems(),
),
工作演示
解决方案1的完整代码
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
List<String> imgSrc = [
"https://randomuser.me/api/portraits/women/84.jpg",
"https://randomuser.me/api/portraits/men/82.jpg",
"https://randomuser.me/api/portraits/women/11.jpg",
"https://randomuser.me/api/portraits/women/61.jpg",
"https://randomuser.me/api/portraits/men/1.jpg",
"https://randomuser.me/api/portraits/men/2.jpg",
"https://randomuser.me/api/portraits/men/3.jpg",
"https://randomuser.me/api/portraits/men/4.jpg",
"https://randomuser.me/api/portraits/men/5.jpg",
"https://randomuser.me/api/portraits/men/6.jpg",
"https://randomuser.me/api/portraits/men/7.jpg",
];
Widget listview() {
List<Widget> imgList = imgSrc
.map((e) => Image.network(e))
.map((e) => Image(
image: e.image,
fit: BoxFit.scaleDown,
width: 64,
))
.toList();
return ListView(
scrollDirection: Axis.horizontal,
children: imgList,
);
}
return Scaffold(
appBar: AppBar(title: const Text('AppBar Demo')),
body: Center(
child: Container(
//width: double.infinity,
child: Text("other content")),
),
bottomSheet: SizedBox(height: 64, child: listview()),
);
}
}
解决方案2的完整代码
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
List<String> imgSrc = [
"https://randomuser.me/api/portraits/women/84.jpg",
"https://randomuser.me/api/portraits/men/82.jpg",
"https://randomuser.me/api/portraits/women/11.jpg",
"https://randomuser.me/api/portraits/women/61.jpg",
"https://randomuser.me/api/portraits/men/1.jpg",
"https://randomuser.me/api/portraits/men/2.jpg",
"https://randomuser.me/api/portraits/men/3.jpg",
"https://randomuser.me/api/portraits/men/4.jpg",
"https://randomuser.me/api/portraits/men/5.jpg",
"https://randomuser.me/api/portraits/men/6.jpg",
"https://randomuser.me/api/portraits/men/7.jpg",
];
List<Widget> _listviewItems() {
return imgSrc
.map((e) => Image.network(e))
.map((e) => Image(
image: e.image,
fit: BoxFit.scaleDown,
width: 64,
))
.toList();
}
Widget w = Container(
child: Stack(
children: [
// Center(
// child: cards.first,
// ),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 64,
child: ListView(
padding: const EdgeInsets.all(0.0),
scrollDirection: Axis.horizontal,
children: _listviewItems(),
),
),
)),
SizedBox(
height: 8,
)
],
)
],
));
return Scaffold(
body: Container(width: double.infinity, child: w),
);
}
}