【问题标题】:Flutter gridview inside listview在列表视图中颤动网格视图
【发布时间】:2019-01-16 20:20:59
【问题描述】:

我想构建像 Ios 应用商店这样的设计,如下图所示。 我想要实现的是有 5 个顶级类别,每个类别都有显示图像的网格。 我也试过这样。

return new Scaffold(
  backgroundColor: Colors.white,
  appBar: buildBar(context),
  // wrap in gesture to dismiss keyboard
  body: new GestureDetector(
    behavior: HitTestBehavior.opaque,
    onPanDown: (detail) {
      FocusScope.of(context).requestFocus(new FocusNode());
    },
    child: new ListView(
      shrinkWrap: true,
      children: <Widget>[
        new Container(
          decoration: new BoxDecoration(color: Colors.grey[400]),
          child: new Column(
            children: <Widget>[
              new SizedBox(height: 15.0),
              new Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  new Icon(Icons.invert_colors,
                      color: Colors.red, size: 45.0),
                  new Text('Top 5',
                      style: new TextStyle(
                          color: Colors.white,
                          fontSize: 25.0,
                          fontWeight: FontWeight.bold)),
                ],
              ),
              new SizedBox(height: 15.0),
            ],
          ),
        ),
        new SizedBox(height: 30.0),
        new ListView.builder(
          shrinkWrap: true,
          itemCount: 5,
          itemBuilder: (BuildContext context, int index) {
            return new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Container(
                  decoration:
                      new BoxDecoration(color: Colors.lightBlue[200]),
                  child: new Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      new Icon(icons[index],
                          size: 30.0),
                      new Padding(
                          padding: const EdgeInsets.only(right: 5.0)),
                      new Text('Category',
                          style: new TextStyle(
                              fontSize: 23.0, fontWeight: FontWeight.bold)),
                    ],
                  ),
                ),
                new SizedBox(height: 5.0),
                new GridView.builder(
                  shrinkWrap: true,
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  gridDelegate:
                      new SliverGridDelegateWithFixedCrossAxisCount(
                          crossAxisCount: 4),
                  itemBuilder: (BuildContext context, int index) {
                    return new GestureDetector(
                        child: new Card(
                          elevation: 5.0,
                          child: new Container(
                            padding: new EdgeInsets.only(
                                bottom: 2.0, right: 3.0),
                            decoration: new BoxDecoration(
                              image: new DecorationImage(
                                fit: BoxFit.cover,
                                image: NetworkImage(
                                    'https://images.unsplash.com/photo-1505535162959-9bbcb4ab22d6?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=0891a99609bf6fdc48842101bef90d67&auto=format&fit=crop&w=500&q=60'),
                              ),
                            ),
                          ),
                        ),
                        onTap: () {
                          print('tapped');
                        });
                  },
                ),
                new SizedBox(height: 20.0),
              ],
            );
          },
        ),
      ],
    ),
  ),
);

但是网格视图没有出现,如果我注释掉网格视图然后显示没有图像的列表只有类别名称。 我试图包装expanded,将shrinkWrap 设置为true,但没有工作。 我一直在寻找,但仍然无法弄清楚。 有人知道怎么解决吗?

编辑:

 return new Scaffold(
  backgroundColor: Colors.white,
  appBar: new AppBar(
    title: new Text('Search'),
  ),
  body: new GestureDetector(
    behavior: HitTestBehavior.opaque,
    onPanDown: (detail) {
      print(detail);
      FocusScope.of(context).requestFocus(new FocusNode());
    },
    child: new ListView(
      shrinkWrap: true,
      children: <Widget>[
        new SizedBox(height: 20.0),
        new Container(
            height: 60.0,
            color: Colors.blue,
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Icon(Icons.hourglass_empty,
                    color: Colors.white, size: 30.0),
                new Padding(padding: const EdgeInsets.only(right: 5.0)),
                new Text('TOP5',
                    style:
                        new TextStyle(color: Colors.white, fontSize: 23.0)),
              ],
            ),
          ),
          new SizedBox(height: 20.0),
        new Container(
          child: new ListView.builder(
            shrinkWrap: true,
            itemCount: 5,
            itemBuilder: (context, index) {
              return new Column(
                children: <Widget>[
                  new Container(
                    height: 50.0,
                    color: Colors.green,
                    child: new Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        new Icon(Icons.format_list_numbered,
                            color: Colors.white),
                        new Padding(
                            padding: const EdgeInsets.only(right: 5.0)),
                        new Text(arr[index],
                            style: new TextStyle(
                                fontSize: 20.0, color: Colors.white)),
                      ],
                    ),
                  ),
                  new Container(
                    height: 150.0,
                    child: new ListView.builder(
                      shrinkWrap: true,
                      scrollDirection: Axis.horizontal,
                      itemCount: 10,
                      itemBuilder: (context, index) {
                        return new GestureDetector(
                          child: new Card(
                            elevation: 5.0,
                            child: new Container(
                              height: MediaQuery.of(context).size.width / 3,
                              width: MediaQuery.of(context).size.width / 3,
                              alignment: Alignment.center,
                              child: new Text('Item $index'),
                            ),
                          ),
                          onTap: () {
                            print(123);
                          },
                        );
                      },
                    ),
                  ),
                  new SizedBox(height: 20.0),
                ],
              );
            },
          ),
        ),
      ],
    ),
  ),
);

【问题讨论】:

    标签: flutter


    【解决方案1】:

    我使用这个属性来达到想要的结果

          shrinkWrap: true,
          physics: ScrollPhysics(),
    

    【讨论】:

      【解决方案2】:

      我在ListView 中使用了颤振GridView,两者都是垂直滚动:

      body: ListView(
        children: <Widget>[
          GridView.count(
            crossAxisCount: 3,
            physics: NeverScrollableScrollPhysics(), // to disable GridView's scrolling
            shrinkWrap: true, // You won't see infinite size error
            children: <Widget>[
              Container(
                height: 24,
                color: Colors.green,
              ),
              Container(
                height: 24,
                color: Colors.blue,
              ),
            ],
          ),
          // ...... other list children. 
        ],
      ),
      

      您可以使用相同的方法在另一个ListView 内颤动水平ListView/GridView

      【讨论】:

      • 在使用此解决方案时触摸/拖动 GridView 中的元素时,我无法拖动/滚动 ListView。 IE。如果我有一个大到足以填满屏幕的 GridView,我将无法再滚动 ListView。我发现可以通过在 GridView 中添加“physics: ScrollPhysics()”来解决这个问题。
      • 是的,这将停止滚动 GridView。并启用列表视图滚动。您可以再做一件事,即使用 CustomScrollView,在该 CustomScrollView 中您可以使用 SliverGridView 和 SliverListView。好吧,我已经更新了我的答案。
      • 不要忘记在 scrollphysics 中添加 shrinkWrap:true ,因为如果您直接在 listview 中添加 gridView 则会抛出错误,因为它无法检测到 gridview 将在哪里结束。尽管收缩包装很昂贵,因为它计算滚动时网格的大小,但它解决了问题
      【解决方案3】:

      如果ListView/GridView 不滚动,physics: ScrollPhysics(), 会起作用,如果父小部件是 SingleChildScrollViewListView/GridView,它们为父小部件提供滚动功能,而不是子小部件,则可能会发生这种情况。

      解决方案:

      Scaffold(
            backgroundColor: Colors.white,
            appBar: new AppBar(
              title: new Text('Search'),
            ),
            body: new ListView(
              shrinkWrap: true,
              physics: ScrollPhysics(),
              children: <Widget>[
                new SizedBox(height: 20.0),
                new Container(
                  child: new ListView.builder(
                    shrinkWrap: true,
                    itemCount: 5,
                    physics: ScrollPhysics(),
                    itemBuilder: (context, index) {
                      return new Column(
                        children: <Widget>[
                          new Container(
                            height: 50.0,
                            color: Colors.green,
                            child: new Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                new Icon(Icons.format_list_numbered,
                                    color: Colors.white),
                                new Padding(
                                    padding: const EdgeInsets.only(right: 5.0)),
                                new Text('List Item',
                                    style: new TextStyle(
                                        fontSize: 20.0, color: Colors.white)),
                              ],
                            ),
                          ),
                          new Container(
                            height: 150.0,
                            child: new ListView.builder(
                              shrinkWrap: true,
                              scrollDirection: Axis.horizontal,
                              itemCount: 10,
                              itemBuilder: (context, index) {
                                return new Card(
                                  elevation: 5.0,
                                  child: new Container(
                                    height: MediaQuery.of(context).size.width / 3,
                                    width: MediaQuery.of(context).size.width / 3,
                                    alignment: Alignment.center,
                                    child: new Text('Item $index'),
                                  ),
                                );
                              },
                            ),
                          ),
                          new SizedBox(height: 20.0),
                        ],
                      );
                    },
                  ),
                ),
              ],
            ),
          ); 
      

      输出:

      【讨论】:

      • 有没有办法将动态数据加载到每个列表项中? @jitsm555
      【解决方案4】:

      当我使用时

       GridView.count(
            shrinkWrap: true,
            crossAxisCount: 2,
            physics: ScrollPhysics(),
      

      物理属性,它对我有用

      【讨论】:

        【解决方案5】:

        您可以尝试在垂直滚动列表中使用水平滚动列表来轻松实现这种布局。

        在你的水平列表和垂直列表中放

        shrinkWrap : true
        

        或者

        将列表包装在 Expanded() 小部件中

        编辑

        这就是我在另一个列表视图中使用列表视图的方式。

                             Container ( child : 
                                ListView.builder(
                                    itemBuilder: (context, subMenuIndex) {
                                      return Container(
                                        padding: EdgeInsets.only(left: 20.0),
                                        child: sideMenuStuff.sideMenuData.elementAt(mainIndex).menu.subMenu.elementAt(subMenuIndex).subSubMenu != null
                                            ? ExpansionTile(
                                          title: Text(sideMenuStuff.sideMenuData.elementAt(mainIndex).menu.subMenu.elementAt(subMenuIndex).zero.info.title,
                                          ),
                                          children: <Widget>[
                                            ListView.builder(
                                                shrinkWrap: true,
                                                itemCount: sideMenuStuff.sideMenuData.elementAt(mainIndex).menu.subMenu.elementAt(subMenuIndex).subSubMenu.length,                                     
                                                itemBuilder:
                                                    (context, subSubMenuIndex) {
                                                  return Container(
                                                    padding: EdgeInsets.only(
                                                        left: 40.0,
                                                        top: 10.0,
                                                        bottom: 10.0),
                                                    child:
                                                    GestureDetector(
                                                      onTap:
                                                          () {
                                                        Navigator
                                                            .pop(context);
                                                        Navigator
                                                            .of(context)
                                                            .push(MaterialPageRoute(
                                                            builder: (context) =>
                                                                Products(
                                                                    sideMenuStuff
                                                                        .sideMenuData
                                                                        .elementAt(
                                                                        mainIndex)
                                                                        .menu
                                  ....
                                  ....
                                  );
        

        【讨论】:

        • 感谢您的回答,我将 gridview 更改为水平列表视图,但仍然给我错误提示 Horizontal viewport was given unbounded height 你能告诉我哪里出了问题吗?
        • 再次感谢您,但现在给我这个Incorrect use of ParentDataWidget. Expanded widgets must be placed inside Flex widgets 我应该在哪里扩展?因为我有listview,下面有listview,下面有水平的listview
        • 我刚刚尝试包裹父 listview,这是第一个 listview,但仍然没有任何显示。
        • 我将发布一个代码示例供您更好地理解
        • 感谢您的代码,我能够展示我想要的内容,但如果我向下滚动,我应该会看到数字 5 类别。但我看不到上面图片中的5(我编辑过)。我包装了每个小部件,但当我向下滚动时,“TOP5”并没有消失。你能理解这个吗?我该如何解决?
        猜你喜欢
        • 2022-01-20
        • 1970-01-01
        • 2019-04-08
        • 1970-01-01
        • 1970-01-01
        • 2014-12-08
        • 2020-06-19
        • 2020-11-20
        • 2018-12-21
        相关资源
        最近更新 更多