类别网格,其中图像和类别名称显示在图像下方
Widget build(BuildContext context) {
return FutureBuilder(
future: categoriesService.getCategories(1),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.error != null) {
print('error ${snapshot.error}');
return Text(snapshot.error.toString());
}
// YOUR CUSTOM CODE GOES HERE
return Container(
// padding: const EdgeInsets.all(0.0),
child: GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
// childAspectRatio: 19 / 12,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
),
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
Category category = snapshot.data[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
child: Image.network(
category.image,
fit: BoxFit.cover,
),
decoration: BoxDecoration(
border: Border.all(width: 1.0),
),
),
Text(category.name)
],
);
},
),
);
} else {
return new CircularProgressIndicator();
}
});
}
我的子项具有图像和类别名称。如图所示,当前子项溢出,我们无法在图像下方看到类别名称,并且无法删除图像和边框之间的顶部空间。
原始设计在这里
答案 0 :(得分:3)
我找到了一种动态设置最大子项的纵横比到我们的Grid视图的方法。
它是如何工作的 ?
首先,请查看此答案。如何在overlayEntery
How to get a height of a Widget?
之后,我们在childAspectRatio的网格视图中设置正确的宽高比(使用overlayEntery进行测量)。
希望这对您有所帮助。
我做个例子...
https://dartpad.dev/4821d71ec618d7d1f1f92f27458fde61
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class GridItemModel {
String longtext;
GlobalKey itemKey;
double width;
double height;
GridItemModel(this.longtext) {
itemKey = GlobalKey();
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _StateHomePage();
}
}
class _StateHomePage extends State<MyHomePage> {
// this first assign very important don't change it .
// if you change this part overlayEntry cant find biggest widget correctly .(cant see not scrolled items.)
// for test change to 1/1 and see what happening.
var myDynamicAspectRatio = 1000 / 1;
OverlayEntry sticky;
List<GridItemModel> myGridList = new List();
double maxHeight = 0;
double maxWidth = 0;
@override
void initState() {
if (sticky != null) {
sticky.remove();
}
sticky = OverlayEntry(
builder: (context) => stickyBuilder(context),
);
WidgetsBinding.instance.addPostFrameCallback((_) {
Overlay.of(context).insert(sticky);
setState(() {});
});
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.addPostFrameCallback((_) {
sticky.remove();
});
super.dispose();
}
@override
Widget build(BuildContext context) {
final title = 'Grid List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: GridView.count(
crossAxisCount: 2,
childAspectRatio: myDynamicAspectRatio,
children: List.generate(20, (index) {
myGridList.add(new GridItemModel(longTextMaker(index)));
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
key: myGridList[index].itemKey,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.teal[index*100]
),
child: Text(
'Item $index' + myGridList[index].longtext,
style: Theme.of(context).textTheme.headline5,
),
),
],
);
}),
),
),
);
}
String longTextMaker(int count){
String result = "longText";
for(int i = 0 ; i < count; i++){
result += "longText" ;
}
return result;
}
shouldUpdateGridList(){
bool isChanged =false;
for(GridItemModel gi in myGridList) {
if(gi.width != null) {
if (gi.height > maxHeight) {
maxHeight = gi.height;
maxWidth = gi.width;
isChanged = true;
}
}
}
if(isChanged) {
myDynamicAspectRatio = maxWidth / maxHeight;
print("AspectRatio" + myDynamicAspectRatio.toString());
}
}
Widget stickyBuilder(BuildContext context) {
for(GridItemModel gi in myGridList) {
if(gi.width == null) {
final keyContext = gi.itemKey.currentContext;
if (keyContext != null) {
final box = keyContext.findRenderObject() as RenderBox;
print(box.size.height);
print(box.size.width);
gi.width = box.size.width;
gi.height = box.size.height;
}
}
}
shouldUpdateGridList();
return Container();
}
}
答案 1 :(得分:3)
儿童长宽比基本上是网格相对于设备的宽度/高度。
因此,假设您希望每个网格的宽度为30,高度为20,则将纵横比设置为3/2。
我建议您直接从Flutter团队观看video。尽管它与AspectRatio小部件有关,但有关设置AspectRatio的部分适用于此问题
答案 2 :(得分:2)
您可以使用设备的宽度和高度来动态计算宽高比。我根据您的代码添加了一个代码示例,展示了如何完成此操作。请注意,您可能需要略微调整所提供的宽高比,以符合您的特定要求。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class Category {
String name;
String image;
Category({this.name, this.image,});
}
class CategoriesService {
Future<List<Category>> getCategories(int value) async {
return <Category>[
Category(
name: 'FRESH CHICKEN',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'FRESH MUTTON',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'HALAL FROZEN FISH',
image: 'https://picsum.photos/400/300',
),
Category(
name: '2X STORE',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'FROZEN NONVEG DELIGHTS',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'FROZEN VEG DELIGHTS',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'DAL & PULSES',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'SPICES',
image: 'https://picsum.photos/400/300',
),
Category(
name: 'DRY FRUITS & NUTS',
image: 'https://picsum.photos/400/300',
),
];
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: CategoriesService().getCategories(1),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.error != null) {
print('error ${snapshot.error}');
return Text(snapshot.error.toString());
}
// YOUR CUSTOM CODE GOES HERE
return Container(
// padding: const EdgeInsets.all(0.0),
child: GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.4),
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
),
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
Category category = snapshot.data[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
child: Image.network(
category.image,
fit: BoxFit.cover,
),
decoration: BoxDecoration(
border: Border.all(width: 1.0),
),
),
Padding(
padding: const EdgeInsets.only(
top: 8.0,
),
child: Text(
category.name,
textAlign: TextAlign.center,
),
)
],
);
},
),
);
} else {
return new CircularProgressIndicator();
}
}),
),
);
}
}
如果尚未查看GridView
小部件的宽高比,您可能会发现以下答案很有用。
答案 3 :(得分:-1)
您可以像这样在GridView.builder中提供childAspectRatio:
GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount:3,childAspectRatio: (150.0 / 220.0)
)
)