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

Vip*_*sri 14 gridview dart staggered-gridview flutter

如何在扑动中实现这个复杂的视图?

我正在尝试GridView使用n列实现,并且子应该具有一定的宽高比(比如说1.3),但是孩子的高度应该是(在Android术语中包装内容).

我被困了,因为我理解GridView childAspectRatio:1.3(默认值:1)总是以相同的宽高比而不是动态内容来布置孩子.

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

使用案例:我正在尝试实现如下所示的视图,其中图像被包裹,height = wrap content以便在具有拉伸高度的图像看起来很好并且形成StaggeredGridView类似结构的情况下.

示例图像

Rom*_*tel 14

编辑:StaggeredTile.fit在0.2.0中添加了构造函数.有了它你应该能够建立你的应用程序;-).

动态磁贴大小

第一条评论: 现在使用StaggeredGridView,布局和子渲染完全独立.所以@rmtmckenzie说,你必须得到图像大小来创建你的瓷砖.然后你可以使用StaggeredTile.count构造函数的双值mainAxisCellCount参数:new StaggeredTile.count(x, x*h/w)(这里h是你的形象和高度w.它的宽度,以便与瓷砖具有相同的高宽比为你的形象.

您想要完成的工作需要更多的工作,因为您希望在图像下方有一些区域并提供一些信息.为此我认为你必须在创建它之前计算它的实际宽度并使用StaggeredTile.extent构造函数.

我知道这并不理想,我正在开发一种创建布局的新方法.我希望它有助于构建像你这样的场景.

  • 你没有添加任何关于如何使用 `StaggeredTile.fit` 的例子。 (7认同)

Bla*_*nka 12

首先让我告诉你我是如何走到这里的:

在我的应用程序中,我想要一个网格视图来显示我的广告卡,所有来自服务器数据库的数据和图像都来自服务器,并且图像的大小不同。我曾经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,
  //..
Run Code Online (Sandbox Code Playgroud)

如您所见,它不会对所有卡片都具有动态性。我像你一样来到这里,并试图使用所有很棒的答案,你必须解决一些问题才能理解如何,但这些答案中的任何一个都完全解决了我的问题。

使用@RomainRastel回答并感谢他的StaggeredGridView包裹。我必须使用StaggeredGridView.count我的构造函数来映射所有卡片,而对于staggeredTiles属性,我必须再次映射所有卡片并为每个StaggeredTile.fit(2).

我相信你还没有明白,所以让我们尝试一个简单的例子,这样你就不需要去其他地方找到答案:

首先添加依赖pubspec.yaml,现在版本是0.2.5. 您可以在此处查看最新版本。

dependencies:
 flutter_staggered_grid_view: ^0.2.5
Run Code Online (Sandbox Code Playgroud)

如果您要从 Internet 获取数据或者要复制粘贴此示例,则还必须添加此依赖项:http: ^0.12.0.

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),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您有任何问题,这里是git 存储库中的完整示例

Flutter 灵活的网格视图示例

祝你好运!


azi*_*iza 6

这里有两件事:

  1. 有一个现有的包来做这样的布局

  2. 为了使图像BoxFit.coverDecorationImage小部件上看起来很好用。

这里的包 repo 中有大量示例

我只是使用了一些示例并将其修改为包含图片:

在此处输入图片说明

class GridViewExample extends StatefulWidget {
  @override
  _GridViewExampleState createState() => new _GridViewExampleState();
}

class _GridViewExampleState extends State<GridViewExample> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Padding(
        padding: const EdgeInsets.all(8.0),
        child: new StaggeredGridView.countBuilder(
  crossAxisCount: 4,
  itemCount: 8,
  itemBuilder: (BuildContext context, int index) => new Container(
        decoration: new BoxDecoration(
          image: new DecorationImage(
            image: new NetworkImage("https://i.imgur.com/EVTkpZL.jpg"),
            fit: BoxFit.cover
          )
        )

        ),

  staggeredTileBuilder: (int index) =>
      new StaggeredTile.count(2, index.isEven ? 2 : 1),
  mainAxisSpacing: 4.0,
  crossAxisSpacing: 4.0,
),),

    );
  }
}
Run Code Online (Sandbox Code Playgroud)