Skip to Content
Flutter📐 Layouts🔲 GridView

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: [...], )
RatioKết quả
1.0Hình vuông
2.0Rộng gấp đôi cao
0.5Cao gấp đôi rộng
16/9Video 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ế

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

ConstructorKhi 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
PropertyMô tả
crossAxisCountSố cột
maxCrossAxisExtentChiều rộng tối đa
mainAxisSpacingSpacing dọc
crossAxisSpacingSpacing ngang
childAspectRatioTỷ lệ w/h
Last updated on