Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
根据颤振中的动态内容调整GridView子级高度_Gridview_Dart_Flutter_Staggered Gridview - Fatal编程技术网

根据颤振中的动态内容调整GridView子级高度

根据颤振中的动态内容调整GridView子级高度,gridview,dart,flutter,staggered-gridview,Gridview,Dart,Flutter,Staggered Gridview,如何在颤振中实现此复杂视图? 我试图实现一个包含n列的GridView,子对象应该具有一定的纵横比(比如1.3),但子对象的高度应该是(用Android术语包装内容) 我被卡住了,因为作为fas,我理解GridView的childAspectRatio:1.3(默认值:1)总是以相同的纵横比布置子对象,而不是动态内容 注意:子对象应根据图像的高度扩展其高度 用例:我试图实现如下视图,其中图像被包装height=wrap content,以便在这种情况下,具有拉伸高度的图像可以看起来很好,并形成类

如何在颤振中实现此复杂视图?

我试图实现一个包含n列的
GridView
,子对象应该具有一定的纵横比(比如1.3),但子对象的高度应该是(用Android术语包装内容)

我被卡住了,因为作为fas,我理解GridView的
childAspectRatio:1.3
(默认值:1)总是以相同的纵横比布置子对象,而不是动态内容

注意:子对象应根据图像的高度扩展其高度

用例:我试图实现如下视图,其中图像被包装
height=wrap content
,以便在这种情况下,具有拉伸高度的图像可以看起来很好,并形成类似
StaggeredGridView
的结构


这里有两件事:

  • 做这样的布局是有必要的

  • 为了使图像看起来更好,请使用
    DecorationImage
    小部件上的
    BoxFit.cover

  • 这本书中有很多例子

    我刚刚使用了其中一个示例,并对其进行了修改,以包含图片:

    类GridViewExample扩展StatefulWidget{
    @凌驾
    _GridViewExampleState createState()=>new_GridViewExampleState();
    }
    类\u GridViewExampleState扩展状态{
    @凌驾
    小部件构建(构建上下文){
    归还新脚手架(
    车身:新衬垫(
    填充:常数边集全部(8.0),
    子项:新建EdgridView.countBuilder(
    交叉轴计数:4,
    物品计数:8,
    itemBuilder:(BuildContext上下文,int索引)=>新容器(
    装饰:新盒子装饰(
    图片:新装饰图片(
    图像:新的网络图像(“https://i.imgur.com/EVTkpZL.jpg"),
    适合:BoxFit.cover
    )
    )
    ),
    交错文件生成器:(int索引)=>
    新的交错文件计数(2,index.isEven?2:1),
    主轴间距:4.0,
    交叉轴间距:4.0,
    ),),
    );
    }
    }
    
    对于任何一种相对简单的方法(即,在没有深入了解颤振中布局的工作原理的情况下),您都需要在构建任何内容之前获得图像的大小。它描述了如何使用和来实现这一点

    然后你可以使用@aziza的例子,一旦你知道了图像的基本尺寸

    另一种方法是在存储图像/URL列表的任何位置存储图像大小或至少是纵横比(我不知道您是如何填充图像列表的,因此我无法帮助您)

    如果您希望它完全基于图像的大小,而不是像网格一样,那么您可以使用小部件来实现。不过有一个警告——我相信它不会很好地处理大量的项目,因为它每次都必须把所有的孩子都放在外面,但我可能错了。如果您没有大量的项目,可以使用Flow+a作为滚动部分

    如果你想要有大量的项目(和/或想做一些像动态加载新项目的事情),你可能需要做一些事情-我认为这会更有效,但你仍然需要做一些事情来了解图像的大小

    最后一个可能的解决方案(我不知道这到底是怎么回事)是让两个可滚动视图并排并同步它们的位置。不过,您必须将shrinkwrap设置为true,这样才能进行滚动,而且您还必须知道每个图像的高度,这样才能决定将每个图像放在哪一侧


    希望这至少能帮助你开始

    编辑:我在0.2.0中添加了构造函数
    交错文件.fit
    。有了它,你应该能够构建你的应用程序;-)

    第一条评论: 现在,布局和子渲染是完全独立的。因此,正如@rmtmckenzie所说,您必须获得图像大小才能创建瓷砖。 然后,您可以使用
    StaggedTitle.count
    构造函数,为
    mainAxisCellCount
    参数设置一个双值:
    新建StaggedTitle.count(x,x*h/w)
    (其中
    h
    是图像的高度,而
    w
    是图像的宽度。这样,具有相同纵横比的平铺就可以与图像具有相同的纵横比

    您想要完成的工作将需要更多的工作,因为您希望在图像下方有一个包含一些信息的区域。为此,我认为您必须在创建平铺之前计算平铺的实际宽度,并使用
    交错文件.extent
    构造函数


    我知道这并不理想,我目前正在研究一种新的方式来创建布局。我希望这将有助于构建像您这样的场景。

    首先让我告诉您我是如何在这里结束的:

    在我的应用程序中,我需要一个网格视图来显示我的广告卡,所有来自服务器数据库的数据和图像都来自服务器,并且图像大小不同。我使用
    FutureBuilder
    将这些数据映射到
    GridView
    。首先,我尝试使用:

    double cardWidth = MediaQuery.of(context).size.width / 3.3;
    double cardHeight = MediaQuery.of(context).size.height / 3.6;
    //....
    GridView.count(
      childAspectRatio: cardWidth / cardHeight,
      //..
    
    正如你所看到的,它不会对所有的卡片都是动态的。我和你一样来到这里,尝试使用所有的答案,这些答案都很好,你必须解决一些问题来了解如何解决,但这些答案中的任何一个都完全解决了我的问题

    使用@ROMAINRUSTEL回答并感谢他的软件包。我必须使用
    StaggedGridView.count
    作为映射所有卡片的构造函数,对于
    StaggedTitles
    属性,我必须再次映射所有卡片,并为每个
    StaggedTitle.fit(2)

    我相信您仍然没有理解,因此让我们尝试一个简单的示例,这样您就不需要去其他地方寻找答案:

    首先将依赖项添加到
    pubspec.yaml
    ,现在的版本是
    0.2.5
    。您可以签出最新的版本

    如果您正在从internet获取数据,或者
    double cardWidth = MediaQuery.of(context).size.width / 3.3;
    double cardHeight = MediaQuery.of(context).size.height / 3.6;
    //....
    GridView.count(
      childAspectRatio: cardWidth / cardHeight,
      //..
    
    dependencies:
     flutter_staggered_grid_view: ^0.2.5
    
    import 'package:flutter/material.dart';
    
    //this is what you need to have for flexible grid
    import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
    
    //below two imports for fetching data from somewhere on the internet
    import 'dart:convert';
    import 'package:http/http.dart' as http;
    
    //boilerplate that you use everywhere
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: "Flexible GridView",
          home: HomePage(),
        );
      }
    }
    
    //here is the flexible grid in FutureBuilder that map each and every item and add to a gridview with ad card
    class HomePage extends StatelessWidget {
      //this is should be somewhere else but to keep things simple for you,
      Future<List> fetchAds() async {
        //the link you want to data from, goes inside get
        final response = await http
            .get('https://blasanka.github.io/watch-ads/lib/data/ads.json');
    
        if (response.statusCode == 200) return json.decode(response.body);
        return [];
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Dynamic height GridView Demo"),
          ),
          body: FutureBuilder<List>(
              future: fetchAds(),
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if (snapshot.hasData) {
                  return new Padding(
                    padding: const EdgeInsets.all(4.0),
                    //this is what you actually need
                    child: new StaggeredGridView.count(
                      crossAxisCount: 4, // I only need two card horizontally
                      padding: const EdgeInsets.all(2.0),
                      children: snapshot.data.map<Widget>((item) {
                        //Do you need to go somewhere when you tap on this card, wrap using InkWell and add your route
                        return new AdCard(item);
                      }).toList(),
    
                      //Here is the place that we are getting flexible/ dynamic card for various images
                      staggeredTiles: snapshot.data
                          .map<StaggeredTile>((_) => StaggeredTile.fit(2))
                          .toList(),
                      mainAxisSpacing: 3.0,
                      crossAxisSpacing: 4.0, // add some space
                    ),
                  );
                } else {
                  return Center(
                      child:
                          new CircularProgressIndicator()); // If there are no data show this
                }
              }),
        );
      }
    }
    
    //This is actually not need to be a StatefulWidget but in case, I have it
    class AdCard extends StatefulWidget {
      AdCard(this.ad);
    
      final ad;
    
      _AdCardState createState() => _AdCardState();
    }
    
    class _AdCardState extends State<AdCard> {
      //to keep things readable
      var _ad;
      String _imageUrl;
      String _title;
      String _price;
      String _location;
    
      void initState() {
        setState(() {
          _ad = widget.ad;
          //if values are not null only we need to show them
          _imageUrl = (_ad['imageUrl'] != '')
              ? _ad['imageUrl']
              : 'https://uae.microless.com/cdn/no_image.jpg';
          _title = (_ad['title'] != '') ? _ad['title'] : '';
          _price = (_ad['price'] != '') ? _ad['price'] : '';
          _location = (_ad['location'] != '') ? _ad['location'] : '';
        });
    
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Card(
          semanticContainer: false,
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(4.0)),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Image.network(_imageUrl),
              Text(_title),
              Text('\$ $_price'),
              Text(_location),
            ],
          ),
        );
      }
    }
    
    crossAxisCount: 
    
    StaggeredTile.fit(value)
    
    crossAxisCount: 2,
    staggeredTileBuilder: (int index) => new StaggeredTile.fit(1),
    
    class _MyHomePageState extends State<MyHomePage> {
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              body: Container(
                child: FutureBuilder(
                  future: NetworkHelper.getData(),
                  builder: (BuildContext context, AsyncSnapshot snapshot) {
                    if (snapshot.data == null)
                      return Center(child: CircularProgressIndicator());
                    else {
                      var data = snapshot.data;
                      print(data);
                      List<dynamic> jsonData = jsonDecode(snapshot.data);
                      return StaggeredGridView.countBuilder(
                        crossAxisCount: 4,
                        itemCount: jsonData.length,
                        itemBuilder: (BuildContext context, int index) {
                          JsonModelClass models =
                              JsonModelClass.fromJson(jsonData[index]);
                          String url = models.urls.regular;
                          return GestureDetector(
                            onTap: () {
                              print(url);
                            },
                            child: Card(
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                children: [
                                  Image.network(url),
                                  Container(
                                    child: Row(
                                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                      crossAxisAlignment: CrossAxisAlignment.center,
                                      children: [
                                        Text("${models.user.name}"),
                                        Card(
                                          child: Padding(
                                            padding: const EdgeInsets.all(3.0),
                                            child: Row(
                                              mainAxisAlignment:
                                                  MainAxisAlignment.spaceEvenly,
                                              children: [
                                                Icon(
                                                  Icons.favorite,
                                                  color: Colors.red,
                                                ),
                                                SizedBox(
                                                  width: 6,
                                                ),
                                                Text("${models.likes}")
                                              ],
                                            ),
                                          ),
                                        ),
                                      ],
                                    ),
                                  )
                                ],
                              ),
                            ),
                          );
                        },
                        staggeredTileBuilder: (int index) {
                          JsonModelClass models =
                              JsonModelClass.fromJson(jsonData[index]);
                          var height = (models.height * 2) /
                              models.width; //calculating respective 'height' of image in view, 'model.height' is image's original height received from json.
                          return StaggeredTile.count(
                              2,
                              height +
                                  0.5); //Adding extra 0.5 space for other content under the image
                        },
                        mainAxisSpacing: 4,
                        crossAxisSpacing: 4,
                      );
                    }
                  },
                ),
              ),
            );
          }
        }