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

时间:2018-05-03 13:00:24

标签: listview dart flutter

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

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

我意识到,实现此目的的一种方法是将ListView包裹在具有固定高度的Container中。但是,我不一定知道物品的高度:

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

我能够通过RowSingleChildScrollView嵌套在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(),
          // ...
        ],
      ),
    ),
  ],
);

10 个答案:

答案 0 :(得分:8)

只需将shrink的{​​{1}}属性设置为ListView,它将适合空间而不是扩展。

示例:

true

答案 1 :(得分:5)

类似于 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,
      ),
    );

  }  

答案 2 :(得分:4)

这与此处提出的问题非常相似:Flutter ListView.builder() widget's cross Axis is taking up the entire Screen height

我相信 ListViews 要求每个项目都具有相同的横轴大小。这意味着在这种情况下,我们无法为每个对象设置唯一的高度,交叉轴大小是固定的。

如果您想让子项本身唯一控制可滚动的高度,那么您可以使用 SingleChildScrollViewRow (注意:确保设置滚动方向:Axis.horizo​​ntal) output

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')),
                    ),
                  ],
                ),
              )),
        ),
      ),
    );
  }
}

答案 3 :(得分:3)

我使用的是容器的水平listview构建器,因此为了使容器不占据全部高度,我只用Center将其包裹起来即可,并且效果很好。

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

答案 4 :(得分: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);

        },)
      )  ,

答案 5 :(得分: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(),
        ));

答案 6 :(得分: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..
      ]);
    }

答案 7 :(得分:1)

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

SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
    children: [...],
  ),
);

答案 8 :(得分:0)

使用ConstrainedBox设置minHeightmaxHeight

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

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

  ),
)

答案 9 :(得分:0)

如果您不希望 listview 强制您的小部件适合横轴,请确保将它们放置在 Column() 或 Row() 小部件中,而不是直接将其放置在 listview() 中

Image img = ImageIO.read(new File("background.jpg");
public void paint(Graphics g)
{
    // Draw the previously loaded image to Component.
    g.drawImage(img, 0, 0, null);

}
相关问题