Flutter - 布局网格
Posted
技术标签:
【中文标题】Flutter - 布局网格【英文标题】:How to create GridView Layout in Flutter 【发布时间】:2017-10-26 07:09:22 【问题描述】:我正在尝试在颤动中布局一个 4x4 的瓷砖网格。我设法用列和行来做到这一点。但现在我找到了GridView
组件。谁能提供一个如何使用它的例子?
我无法真正理解文档。我似乎没有得到我想要的结果。
【问题讨论】:
【参考方案1】:GridView
用于实现材料grid lists。如果您知道您有固定数量的项目并且不是很多(16 个很好),您可以使用GridView.count
。但是,您应该注意 GridView
是可滚动的,如果这不是您想要的,最好只使用行和列。
import 'dart:collection';
import 'package:flutter/scheduler.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
void main()
runApp(new MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.orange,
),
home: new MyHomePage(),
);
class MyHomePage extends StatelessWidget
@override
Widget build(BuildContext context)
return new Scaffold(
appBar: new AppBar(
title: new Text('Grid Demo'),
),
body: new GridView.count(
crossAxisCount: 4,
children: new List<Widget>.generate(16, (index)
return new GridTile(
child: new Card(
color: Colors.blue.shade200,
child: new Center(
child: new Text('tile $index'),
)
),
);
),
),
);
【讨论】:
例如,如果有 8 个项目,我如何在中心显示网格视图【参考方案2】:将图像加载到图块中的简单示例。
import 'package:flutter/material.dart';
void main()
runApp( MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return Container(
color: Colors.white30,
child: GridView.count(
crossAxisCount: 4,
childAspectRatio: 1.0,
padding: const EdgeInsets.all(4.0),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
children: <String>[
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
'http://www.for-example.org/img/main/forexamplelogo.png',
].map((String url)
return GridTile(
child: Image.network(url, fit: BoxFit.cover));
).toList()),
);
Flutter Gallery 应用包含一个真实世界的示例,可以在 here 找到。
【讨论】:
例如,如果有 8 个项目,我如何在中心显示网格视图 请看***.com/questions/59004532/index-flutter-grid-view【参考方案3】:请访问此repo。
Widget _gridView()
return GridView.count(
crossAxisCount: 4,
padding: EdgeInsets.all(4.0),
childAspectRatio: 8.0 / 9.0,
children: itemList
.map(
(Item) => ItemList(item: Item),
)
.toList(),
);
下面的截图包含 crossAxisCount: 2
【讨论】:
这个 childAspectRatio: 8.0 / 9.0 是如何计算的?找到 8.0/9.0 的过程是什么?? 请看***.com/questions/59004532/index-flutter-grid-view 上面的链接失效了【参考方案4】:GridView
中针对不同场景的命名构造函数很少,
构造函数
GridView
GridView.builder
GridView.count
GridView.custom
GridView.extent
下面是GridView
构造函数的例子:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: ExampleGrid(),
),
);
class ExampleGrid extends StatelessWidget
List<String> images = [
"https://uae.microless.com/cdn/no_image.jpg",
"https://images-na.ssl-images-amazon.com/images/I/81aF3Ob-2KL._UX679_.jpg",
"https://www.boostmobile.com/content/dam/boostmobile/en/products/phones/apple/iphone-7/silver/device-front.png.transform/pdpCarousel/image.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgUgs8_kmuhScsx-J01d8fA1mhlCR5-1jyvMYxqCB8h3LCqcgl9Q",
"https://ae01.alicdn.com/kf/HTB11tA5aiAKL1JjSZFoq6ygCFXaw/Unlocked-Samsung-GALAXY-S2-I9100-Mobile-Phone-android-Wi-Fi-GPS-8-0MP-camera-Core-4.jpg_640x640.jpg",
"https://media.ed.edmunds-media.com/gmc/sierra-3500hd/2018/td/2018_gmc_sierra-3500hd_f34_td_411183_1600.jpg",
"https://hips.hearstapps.com/amv-prod-cad-assets.s3.amazonaws.com/images/16q1/665019/2016-chevrolet-silverado-2500hd-high-country-diesel-test-review-car-and-driver-photo-665520-s-original.jpg",
"https://www.galeanasvandykedodge.net/assets/stock/ColorMatched_01/White/640/cc_2018DOV170002_01_640/cc_2018DOV170002_01_640_PSC.jpg",
"https://media.onthemarket.com/properties/6191869/797156548/composite.jpg",
"https://media.onthemarket.com/properties/6191840/797152761/composite.jpg",
];
@override
Widget build(BuildContext context)
return Scaffold(
body: GridView(
physics: BouncingScrollPhysics(), // if you want ios bouncing effect, otherwise remove this line
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),//change the number as you want
children: images.map((url)
return Card(child: Image.network(url));
).toList(),
),
);
如果您希望您的 GridView 项目根据内容是动态的,您可以用几行代码来做到这一点,但最简单的方法是使用 StaggeredGridView
包。我已通过示例here 提供了答案。
以下是GridView.count
的示例:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: ExampleGrid(),
),
);
class ExampleGrid extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
body: GridView.count(
crossAxisCount: 4,
children: List.generate(40, (index)
return Card(
child: Image.network("https://robohash.org/$index"),
); //robohash.org api provide you different images for any number you are giving
),
),
);
上面sn-p的截图:
SliverGridView
的示例:
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: ExampleGrid(),
),
);
class ExampleGrid extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
body: CustomScrollView(
primary: false,
slivers: <Widget>[
SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: SliverGrid.count(
crossAxisSpacing: 10.0,
crossAxisCount: 2,
children: List.generate(20, (index)
return Card(child: Image.network("https://robohash.org/$index"));
),
),
),
],
)
);
【讨论】:
请看***.com/questions/59004532/index-flutter-grid-view 谢谢,物理:BouncingScrollPhysics() 也是 android 所必需的【参考方案5】:使用适合您需要的任何一个。
GridView.count(...)
GridView.count(
crossAxisCount: 2,
children: <Widget>[
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
],
)
GridView.builder(...)
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (_, index) => FlutterLogo(),
itemCount: 4,
)
GridView(...)
GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: <Widget>[
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
],
)
GridView.custom(...)
GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
childrenDelegate: SliverChildListDelegate(
[
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
],
),
)
GridView.extent(...)
GridView.extent(
maxCrossAxisExtent: 400,
children: <Widget>[
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
],
)
输出(所有人都一样):
【讨论】:
一篇文章中的所有解决方案,谢谢。他们之间有什么不同? @DolDurma 谢谢,这些小部件之间不应该有任何“差异”之类的东西,它们旨在用于不同的用例,所以请使用更适合您需要的那个。 2 号是个不错的选择,感谢这篇文章很有帮助 maxCrossAxisExtent 有什么意义? @DolDurma 在GridView.extent
中,您指定maxCrossAxisExtent
,它告诉孩子即使有可用空间也不要超过这个宽度。在我的示例中,我使用了 400
,这没有多大意义,请选择一些较小的值,例如 100
,而您正在强迫孩子们单独保持 <=100
宽度。以上是关于Flutter - 布局网格的主要内容,如果未能解决你的问题,请参考以下文章