首先让我告诉你我是如何来到这里的:
在我的应用程序中,我想要一个网格视图来展示广告卡片以及从服务器数据库中获取的所有数据和图片,而图片大小不同且来自服务器。我使用了 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,
//..
如你所见,它不会对所有卡片产生动态效果。我和你一样来到这里,尝试使用所有伟大的答案,并且你必须花点时间去理解如何去解决问题,但是没有一个答案完全解决了我的问题。
使用@RomainRastel的答案,以及感谢他的StaggeredGridView
包。我必须使用StaggeredGridView.count
作为构造函数来映射所有卡片,对于staggeredTiles
属性,我必须再次将所有卡片映射并添加每个StaggeredTile.fit(2)
。
我确定你还是没看懂,所以让我们尝试一个简单的例子,这样你就不需要去其他地方寻找答案:
首先,在pubspec.yaml
中添加依赖项,现在版本是0.2.5
。你可以在这里查看最新版本。
dependencies:
flutter_staggered_grid_view: ^0.2.5
如果你从互联网获取数据,或者你将复制粘贴这个示例,你还需要添加这个依赖项:http: ^0.12.0
。
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Flexible GridView",
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
Future<List> fetchAds() async {
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),
child: new StaggeredGridView.count(
crossAxisCount: 4,
padding: const EdgeInsets.all(2.0),
children: snapshot.data.map<Widget>((item) {
return new AdCard(item);
}).toList(),
staggeredTiles: snapshot.data
.map<StaggeredTile>((_) => StaggeredTile.fit(2))
.toList(),
mainAxisSpacing: 3.0,
crossAxisSpacing: 4.0,
),
);
} else {
return Center(
child:
new CircularProgressIndicator());
}
}),
);
}
}
class AdCard extends StatefulWidget {
AdCard(this.ad);
final ad;
_AdCardState createState() => _AdCardState();
}
class _AdCardState extends State<AdCard> {
var _ad;
String _imageUrl;
String _title;
String _price;
String _location;
void initState() {
setState(() {
_ad = widget.ad;
_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),
],
),
);
}
}
如果您有任何问题,这里是一个Git存储库中的完整示例。
祝你好运!
StaggeredTile.fit
的示例。 - Aryeetey Solomon Aryeetey