GridView trong Flutter
1. GridView.count
Grid với số cột cố định:
GridView.count(
crossAxisCount: 2, // 2 cột
children: [
Container(color: Colors.red),
Container(color: Colors.green),
Container(color: Colors.blue),
Container(color: Colors.yellow),
],
)2. GridView.builder
Lazy loading cho danh sách lớn:
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemCount: 100,
itemBuilder: (context, index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
child: Center(child: Text('$index')),
);
},
)3. GridView.extent
Grid với chiều rộng tối đa cho mỗi item:
GridView.extent(
maxCrossAxisExtent: 150, // Mỗi item tối đa 150px rộng
children: [
Container(color: Colors.red),
Container(color: Colors.green),
Container(color: Colors.blue),
],
)4. SliverGridDelegate
FixedCrossAxisCount
Số cột cố định:
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10, // Spacing dọc
crossAxisSpacing: 10, // Spacing ngang
childAspectRatio: 1.5, // Tỷ lệ width/height
),
itemCount: 20,
itemBuilder: (context, index) => Container(color: Colors.blue),
)MaxCrossAxisExtent
Chiều rộng tối đa, số cột tự động:
GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 1.0,
),
itemCount: 20,
itemBuilder: (context, index) => Container(color: Colors.green),
)5. Padding và Spacing
GridView.count(
crossAxisCount: 2,
padding: EdgeInsets.all(16), // Padding cho grid
mainAxisSpacing: 10, // Spacing dọc giữa items
crossAxisSpacing: 10, // Spacing ngang giữa items
children: [...],
)6. Aspect Ratio
Tỷ lệ chiều rộng / chiều cao của item:
GridView.count(
crossAxisCount: 2,
childAspectRatio: 16 / 9, // Wide items
children: [...],
)| Ratio | Kết quả |
|---|---|
1.0 | Hình vuông |
2.0 | Rộng gấp đôi cao |
0.5 | Cao gấp đôi rộng |
16/9 | Video ratio |
7. shrinkWrap
Giống ListView, co grid theo nội dung:
Column(
children: [
Text('Header'),
GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
Container(color: Colors.red, height: 50),
Container(color: Colors.blue, height: 50),
],
),
Text('Footer'),
],
)8. Ví dụ thực tế
Photo Gallery
GridView.builder(
padding: EdgeInsets.all(8),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
),
itemCount: photos.length,
itemBuilder: (context, index) {
return ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Image.network(
photos[index],
fit: BoxFit.cover,
),
);
},
)Product Grid
GridView.builder(
padding: EdgeInsets.all(16),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
childAspectRatio: 0.7, // Cao hơn rộng
),
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Image.network(product.image, fit: BoxFit.cover),
),
Padding(
padding: EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(product.name, style: TextStyle(fontWeight: FontWeight.bold)),
Text('\$${product.price}'),
],
),
),
],
),
);
},
)Icon Grid
GridView.count(
crossAxisCount: 4,
padding: EdgeInsets.all(16),
mainAxisSpacing: 16,
crossAxisSpacing: 16,
children: [
_buildIconItem(Icons.home, 'Home'),
_buildIconItem(Icons.search, 'Search'),
_buildIconItem(Icons.favorite, 'Favorite'),
_buildIconItem(Icons.settings, 'Settings'),
_buildIconItem(Icons.person, 'Profile'),
_buildIconItem(Icons.notifications, 'Alerts'),
_buildIconItem(Icons.mail, 'Mail'),
_buildIconItem(Icons.camera, 'Camera'),
],
)
Widget _buildIconItem(IconData icon, String label) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, size: 32),
SizedBox(height: 4),
Text(label, style: TextStyle(fontSize: 12)),
],
);
}9. Responsive Grid
LayoutBuilder(
builder: (context, constraints) {
int crossAxisCount = 2;
if (constraints.maxWidth > 600) crossAxisCount = 3;
if (constraints.maxWidth > 900) crossAxisCount = 4;
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
),
itemCount: items.length,
itemBuilder: (context, index) => ItemCard(items[index]),
);
},
)📝 Tóm tắt
| Constructor | Khi nào dùng |
|---|---|
GridView.count() | Số cột cố định, ít items |
GridView.extent() | Chiều rộng item cố định |
GridView.builder() | Nhiều items, lazy loading |
| Property | Mô tả |
|---|---|
crossAxisCount | Số cột |
maxCrossAxisExtent | Chiều rộng tối đa |
mainAxisSpacing | Spacing dọc |
crossAxisSpacing | Spacing ngang |
childAspectRatio | Tỷ lệ w/h |
Last updated on