sin*_*enm 39 listview dart flutter
我正在尝试在Flutter中创建一个水平滚动项目列表,我希望该列表仅根据其子项占用必要的高度.通过设计" ListView尝试扩展以适应其横向可用的空间"(来自Flutter文档),我也注意到它占据了视口的整个高度,但有没有办法让它不做这个?理想情况下类似于此(显然不起作用):
new ListView(
scrollDirection: Axis.horizontal,
crossAxisSize: CrossAxisSize.min,
children: <Widget>[
new ListItem(),
new ListItem(),
// ...
],
);
Run Code Online (Sandbox Code Playgroud)
我知道这样做的一种方式是通过包装ListView在Container一个固定的高度.但是,我不一定知道物品的高度:
new Container(
height: 97.0,
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
new ListItem(),
new ListItem(),
// ...
],
),
);
Run Code Online (Sandbox Code Playgroud)
我能够通过嵌套一个砍一起"解决方案" Row中SingleChildScrollView的Column一个mainAxisSize: MainAxisSize.min.但是,对我来说,这不是一个解决方案:
new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: new Row(
children: <Widget>[
new ListItem(),
new ListItem(),
// ...
],
),
),
],
);
Run Code Online (Sandbox Code Playgroud)
fro*_*ega 38
据我了解,您不能在垂直 ListView 中放置水平 ListView 并动态设置其高度。如果您的要求允许(没有无限滚动、少量元素等),您可以使用 SingleChildScrollView 代替。
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [...],
),
);
Run Code Online (Sandbox Code Playgroud)
use*_*613 12
我找到了一种为水平滚动动态调整ListView大小的方法。列表可以有无限个项目,但每个项目应具有相同的高度。
(如果您只有几件物品,或者您的物品必须具有不同的高度,请参阅此答案。)
关键点:
这个想法是测量一个项目,我们称之为“原型”。并基于所有项目高度相同的假设,然后我们设置 的高度ListView以匹配原型项目。
这样,我们就可以避免对任何值进行硬编码,并且当用户在系统中设置更大的字体并导致卡片展开时,列表可以自动调整大小。
演示:
代码:
我制作了一个自定义小部件,名为PrototypeHeight(名称灵感来自IntrinsicHeight)。要使用它,只需传入 aWidget作为“原型”,然后传入水平滚动的ListView,例如:
PrototypeHeight(
prototype: MyItem(),
listView: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (_, index) => MyItem(),
),
)
Run Code Online (Sandbox Code Playgroud)
其实现PrototypeHeight如下(您可以将其粘贴到某处并开始使用它,或者根据需要进行修改):
class PrototypeHeight extends StatelessWidget {
final Widget prototype;
final ListView listView;
const PrototypeHeight({
Key? key,
required this.prototype,
required this.listView,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: [
IgnorePointer(
child: Opacity(
opacity: 0.0,
child: prototype,
),
),
SizedBox(width: double.infinity),
Positioned.fill(child: listView),
],
);
}
}
Run Code Online (Sandbox Code Playgroud)
说明:
让我简要解释一下这是如何工作的。
简而言之,Stack小部件的大小取决于其所有“非定位”子部件。基本上,如果 aStack有 3 个子级,但其中 2 个是Positioned,则Stack会简单地匹配剩余的“未定位”子级。
在这种情况下,我使用“原型项目”作为非定位子项之一,以帮助确定Stack其高度(与原型高度相同)。然后我使用非常宽的宽度SizedBox来帮助确定Stack其宽度(这将与父级的宽度相同,通常是设备的屏幕宽度,因为请记住:约束减小,尺寸增大。)。我还添加了一个Opacity小部件来隐藏原型(这也通过跳过部分渲染管道来提高性能),以及一个IgnorePointer小部件来防止用户交互,以防原型项上有按钮。
接下来,我使用 aPositioned.fill使其子项 ( ListView) 匹配 的大小Stack,而 反过来,将匹配原型项的高度,并匹配父项的宽度。这将是传递给 的约束ListView,因此ListView将创建一个该大小的“视口”,这正是我们想要实现的。
这实际上涵盖了 Flutter 中相当多的概念。我计划稍后制作一个视频教程。
Tah*_*Ali 11
只需将shrink属性设置ListView为true,它将适合空间而不是扩展。
例:
ListView(
shrinkWrap: true, //just set this property
padding: const EdgeInsets.all(8.0),
children: listItems.toList(),
),
Run Code Online (Sandbox Code Playgroud)
(此答案涵盖了项目具有不同尺寸时的解决方法。如果您的项目具有相同的尺寸/高度,请参阅此答案以了解ListView方法。)
如果项目具有不同的尺寸,则不应使用 , 来完成ListView,这是有充分理由的:
AListView可能有很多项目(甚至无限),但找出“最大的一个”需要遍历每个项目,这违背了使用 a 的全部意义ListView(使用该方法动态加载每个项目builder)。
另一方面,Row小部件总是同时布置所有子部件,因此很容易找到最大的部件。所以如果你没有太多的物品(也许少于100件左右),你可以用它Row来代替。如果需要滚动,请Row用SingleChildScrollView.
示例中使用的代码:
Column(
children: [
Container(
color: Colors.green.shade100,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
FlutterLogo(),
FlutterLogo(size: 100),
for (int i = 0; i < 50; i++) FlutterLogo(),
],
),
),
),
const Text('The row has ended.'),
],
)
Run Code Online (Sandbox Code Playgroud)
小智 6
使用ConstrainedBox到集minHeight和maxHeight
ConstrainedBox(
constraints: new BoxConstraints(
minHeight: 35.0,
maxHeight: 160.0,
),
child: new ListView(
shrinkWrap: true,
children: <Widget>[
new ListItem(),
new ListItem(),
],
),
)
Run Code Online (Sandbox Code Playgroud)
类似于 Gene 的回答,但我没有固定数量的小部件要添加。
您也不需要知道小部件的高度。
Widget _horizontalWrappedRow(List data) {
var list = <Widget>[Container(width: 16)]; // container is left padding
//create a new row widget for each data element
data.forEach((element) {
list.add(MyRowItemWidget(element));
});
// add the list of widgets to the Row as children
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: list,
),
);
}
Run Code Online (Sandbox Code Playgroud)
这与此处提出的问题非常相似:Flutter ListView.builder() widget's cross Axis is take up the entire Screen height
我相信 ListViews 要求每个项目都具有相同的横轴大小。这意味着在这种情况下,我们无法为每个对象设置唯一的高度,交叉轴的大小是固定的。
如果您想让子项本身唯一控制可滚动的高度,那么您可以使用与Row配对的SingleChildScrollView (注意:确保设置 scrollDirection: Axis.horizontal)

import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: SafeArea(
child: Container(
// height: 100, // no need to specify here
color: Colors.white,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: <Widget>[
Container(
height: 300,
width: 300,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 100,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
width: 100,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
Container(
height: 300,
width: 300,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 100,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
width: 100,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
Container(
height: 300,
width: 300,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 100,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
width: 100,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
Container(
height: 300,
width: 300,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 100,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
width: 100,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
Container(
height: 300,
width: 300,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 100,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
width: 100,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
),
)),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11962 次 |
| 最近记录: |