颤振:水平列表视图上的最小高度


81

我正在尝试在Flutter中创建项目的水平滚动列表,并且希望该列表仅基于子元素占据必要的高度。通过设计“ListView试图扩展以适应其横向的可用空间”(来自Flutter docs),我也注意到它占用了视口的整个高度,但是有一种方法可以使其不做这个?理想情况下,类似于以下内容(显然不起作用):

new ListView(
  scrollDirection: Axis.horizontal,
  crossAxisSize: CrossAxisSize.min,
  children: <Widget>[
    new ListItem(),
    new ListItem(),
    // ...
  ],
);

我认识到,一个做到这一点的方法是通过包装ListViewContainer一个固定的高度。但是,我不一定知道这些物品的高度:

new Container(
  height: 97.0,
  child: new ListView(
    scrollDirection: Axis.horizontal,
    children: <Widget>[
      new ListItem(),
      new ListItem(),
      // ...
    ],
  ),
);

我能够通过嵌套一个砍一起“解决方案”RowSingleChildScrollViewColumn一个mainAxisSize: MainAxisSize.min。但是,对我来说,这似乎不是解决方案:

new Column(
  mainAxisSize: MainAxisSize.min,
  children: <Widget>[
    new SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: new Row(
        children: <Widget>[
          new ListItem(),
          new ListItem(),
          // ...
        ],
      ),
    ),
  ],
);

10
同样的问题,您能解决吗?
AntonB

2
还没有解决这个问题的方法。
sindrenm

1
谢谢,收缩包装对我没有用。但是您的代码可以:SingleChildScrollView(scrollDirection:Axis.horizo​​ntal,child:new Row(/ *将您的小部件放在这里* /),)如果您找到了“更好的”解决方案,请告诉我们!
Nk54

1
@sindrenm我喜欢Column / SingleChildScrollView / Row组合,因此决定从中简单地构建一个StatelessWidget(我称为ScrollableRow)。我认为它可以完成工作,但我真的看不到任何问题。我只是将其视为明确声明所需内容的一种方法,并通过从中构建小部件,可以以简洁明了的方式使用它。
SamJakob

因此,最后,我们不能使水平线ListView的高度基于子项的高度吗?是 SingleChildScrollView基于ListView唯一的选择?我真的想使用a,ListView因为它在语义上更正确。
Ionel Lupu

Answers:


31

只需将shrink属性设置ListViewtrue,它将适合空间而不是扩展。

例:

ListView(
        shrinkWrap: true, //just set this property
        padding: const EdgeInsets.all(8.0),
        children: listItems.toList(),
      ),

41
shrinkWrapListView沿主轴方向收缩。不是沿着横轴问的。
AnEnigmaticBug

来自api.flutter.dev:收缩包装滚动视图的内容比扩展到允许的最大大小要昂贵得多...请参阅:api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html
Yehuda Kremer

14

使用ConstrainedBox到集minHeightmaxHeight

ConstrainedBox(
  constraints: new BoxConstraints(
    minHeight: 35.0,
    maxHeight: 160.0,
  ),

  child: new ListView(
    shrinkWrap: true,
    children: <Widget>[
      new ListItem(),
      new ListItem(),
    ],

  ),
)

30
在不知道列表项的最小/最大高度的情况下该如何做?
sindrenm

1
@sindrenm您真的必须知道最小/最大高度吗?我的意思是,您可以将高度设置为1到1000之间,例如,所有要做的就是将ListView的大小调整为所需的高度。让我知道我是否错过了一些东西
Texv'5

1
就我而言,ListView增长到适合maxHeight,因此不适合。
fromvega

3

我使用的是容器的水平listview生成器,因此为了阻止容器占据整个高度,我只是将其包裹在Center中,并且效果很好。

itemBuilder: (context, i){
              return Center(child: word_on_line(titles[i]));
          }

1
这是一个非常好的解决方案,非常感谢您,我想知道为什么我以前没有考虑过:D
Alessio

1

使用扩展

 Expanded(
        child:ListView.separated(
          shrinkWrap: true,
        padding: EdgeInsets.all(10),
        separatorBuilder: (BuildContext context, int index) {
          return Align(
            alignment: Alignment.centerRight,
            child: Container(
              height: 0.5,
              width: MediaQuery.of(context).size.width / 1.3,
              child: Divider(),
            ),
          );
        },
        itemCount: dataMasterClass.length,
        itemBuilder: (BuildContext context, int index) {

          Datum datum = dataMasterClass[index];
         return sendItem(datum);

        },)
      )  ,

1

包裹由小部件ColumnmainAxisSize: MainAxisSize.min为我工作。您可以尝试在height此处更改。

var data = [
      {'name': 'Shopping', 'icon': Icons.local_shipping},
      {'name': 'Service', 'icon': Icons.room_service},
      {'name': 'Hotel', 'icon': Icons.hotel},
      {'name': 'More', 'icon': Icons.more}
];

new Container(
        constraints: new BoxConstraints(
          minHeight: 40.0,
          maxHeight: 60.0,
        ),
        color: Colors.transparent,
        child: new ListView(
          scrollDirection: Axis.horizontal,
          children: data
              .map<Widget>((e) => Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      new Container(
                        width: 40,
                        height: 50, // try to change this.
                        color: Colors.transparent,
                        margin: EdgeInsets.only(right: 20, left: 4),
                        child: ClipOval(
                          child: Container(
                            padding: EdgeInsets.all(4),
                            color: Colors.white,
                            child: Icon(
                              e["icon"],
                              color: Colors.grey,
                              size: 30,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ))
              .toList(),
        ));

正是我想要的。谢谢!
乔兰

1

通过应用上述所有解决方案,尚未找到合适的答案,如果我们不知道高度,这将帮助我们设置水平Listview。在所有情况下都必须设置高度。因此我应用了下面的解决方案,该解决方案对我有用,而无需为列表项指定任何高度。@sindrenm在他的问题中已经提到过。所以我想继续研究直到找到可行的解决方案。我应用了wrapWrap:true,但是它将沿主轴收缩ListView。(仅适用于垂直scrollView),并且不沿问题中的要求沿横轴显示。因此在不久的将来,任何人都可以在生产中使用该解决方案,它对我所有的水平清单都非常有用。

//below declared somewhere in a class above any method and assume list has filled from some API.
var mylist = List<myModel>();


SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Row(
          children: [
                for (int index = 0; index < mylist.length; index++) 
                      listItem(mylist[index]);
         ],
        ),
      ),
    ),

    listItem(){
      return Column(
         children[
            widget1(),
            widget2().... etc..
      ]);
    }

1

据我了解,您不能在垂直ListView中有一个水平ListView并动态设置其高度。如果您的要求允许(不允许无限滚动,少量元素等),则可以改用SingleChildScrollView。

SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
    children: [...],
  ),
);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.