Hiển thị dữ liệu dạng lưới với GridView trong Flutter

0 0 0

Người đăng: Coder Tập Sự

Theo Viblo Asia

Bạn có bao giờ tự hỏi làm thế nào các ứng dụng hiển thị thư viện ảnh đẹp mắt, danh sách sản phẩm gọn gàng theo cột, hay thậm chí là các dashboard phức tạp với nhiều ô thông tin được sắp xếp khoa học? Câu trả lời chính là nhờ những widget như GridView.

Trong Flutter, GridView không chỉ đơn thuần là một cách để sắp xếp các item theo dạng lưới, mà còn cung cấp nhiều tùy chọn linh hoạt để bạn tùy chỉnh giao diện, tối ưu hóa hiệu suất cho các danh sách lớn, và tạo ra những trải nghiệm người dùng mượt mà và hấp dẫn.

Bài viết này sẽ đưa bạn đi từng bước, từ những khái niệm cơ bản nhất về GridView, qua các cách tạo và sử dụng phổ biến, đến những lưu ý quan trọng và cách xử lý các lỗi thường gặp. Hãy cùng nhau khám phá sức mạnh của bố cục lưới trong Flutter nhé!

🧠 Mục tiêu bài học

  • Biết cách tạo GridView với dữ liệu tĩnh và động.
  • Hiểu sự khác nhau giữa GridView.count, GridView.builder và làm quen với GridView.extent.
  • Thực hành hiển thị danh sách ảnh hoặc nội dung chia cột đẹp mắt, tùy chỉnh khoảng cách và tỷ lệ khung hình.

📦 GridView là gì?

Trong Flutter, GridView là một widget mạnh mẽ giúp hiển thị các item theo dạng lưới hai chiều, cho phép cuộn cả theo chiều dọc và chiều ngang (tùy cấu hình). Đây là công cụ lý tưởng cho:

  • Thư viện ảnh
  • Danh sách sản phẩm
  • Bố cục nhiều cột trong một không gian cuộn

🚀 Các cách tạo GridView

Flutter cung cấp một số constructor khác nhau cho GridView, mỗi constructor phù hợp với các trường hợp sử dụng khác nhau:

1. GridView.count() – dễ dùng, chỉ định số cột

Đây là cách đơn giản nhất để tạo GridView khi bạn biết trước số cột mong muốn. Tất cả các item con sẽ được tạo ra cùng một lúc.

GridView.count( crossAxisCount: 2, children: [ Container(color: Colors.red), Container(color: Colors.green), Container(color: Colors.blue), Container(color: Colors.orange), ],
)

Thuộc tính quan trọng:

  • crossAxisCount: Xác định số lượng cột hiển thị trên mỗi hàng. Các widget con sẽ tự động được sắp xếp để lấp đầy các cột này.

2. GridView.builder() – linh hoạt và tối ưu

Tương tự như ListView.builder(), constructor này chỉ tạo ra các item khi chúng sắp được hiển thị trên màn hình, giúp tối ưu hóa hiệu suất đáng kể khi làm việc với danh sách dữ liệu lớn hoặc dữ liệu động. Bạn cần cung cấp một SliverGridDelegate để định nghĩa bố cục lưới.

GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemCount: 6, itemBuilder: (context, index) { return Container( color: Colors.primaries[index % Colors.primaries.length], child: Center( child: Text('Mục $index'), ), ); },
)

Thuộc tính quan trọng trong SliverGridDelegateWithFixedCrossAxisCount:

  • crossAxisCount: Số cột trên mỗi hàng.
  • crossAxisSpacing: Khoảng cách giữa các cột.
  • mainAxisSpacing: Khoảng cách giữa các hàng.
  • childAspectRatio: Tỷ lệ giữa chiều rộng và chiều cao của mỗi ô (width / height). Giá trị 1.0 tạo ra các ô vuông.

3. GridView.extent() – chỉ định kích thước tối đa của ô

Với GridView.extent(), bạn chỉ định kích thước tối đa cho phép của mỗi ô theo chiều ngang (maxCrossAxisExtent), và Flutter sẽ tự động tính toán số cột phù hợp dựa trên không gian có sẵn.

GridView.extent( maxCrossAxisExtent: 150, // Kích thước tối đa của mỗi ô theo chiều ngang crossAxisSpacing: 10, mainAxisSpacing: 10, children: List.generate( 8, (index) => Container( color: Colors.amber[100 * (index % 9)], child: Center(child: Text('Item $index')), ), ),
)

Thuộc tính quan trọng:

  • maxCrossAxisExtent: Kích thước tối đa của mỗi ô theo chiều ngang. Flutter sẽ cố gắng tạo ra các cột sao cho không có ô nào vượt quá kích thước này.

Ví dụ đầy đủ

import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget {  Widget build(BuildContext context) { return MaterialApp( home: DanhSachAnh(), ); }
} class ListImage extends StatelessWidget { final List<String> imageUrls = List.generate( 8, (index) => 'https://picsum.photos/200/300?random=$index', );  Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Bộ sưu tập')), body: Padding( padding: const EdgeInsets.all(10), child: GridView.builder( itemCount: imageUrls.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 10, mainAxisSpacing: 10, ), itemBuilder: (context, index) { return ClipRRect( borderRadius: BorderRadius.circular(10), child: Image.network( imageUrls[index], fit: BoxFit.cover, ), ); }, ), ), ); }
}

Ghi nhớ khi làm việc với GridView:

  • Sử dụng GridView.count cho các lưới có số cột cố định và số lượng item nhỏ.
  • GridView.builder là lựa chọn tốt nhất cho danh sách dữ liệu động hoặc số lượng item lớn để tối ưu hiệu suất.
  • GridView.extent hữu ích khi bạn muốn các ô có kích thước chiều ngang tối đa nhất định và để Flutter tự động tính toán số cột.
  • Luôn chú ý đến các thuộc tính crossAxisSpacing, mainAxisSpacing, và childAspectRatio để tạo bố cục lưới đẹp và phù hợp.
  • Khi GridView là con của các widget không giới hạn kích thước (như Column, Row), hãy bọc nó trong Expanded hoặc SizedBox để tránh lỗi bố cục.

Các lỗi thường gặp và cách khắc phục:

  • GridView không cuộn được: Kiểm tra xem GridView có được bọc trong một widget có kích thước xác định theo hướng cuộn hay không (ví dụ: Expanded, SizedBox).
  • Lỗi tràn pixel: Điều chỉnh crossAxisCount, crossAxisSpacing, mainAxisSpacing, và childAspectRatio sao cho phù hợp với kích thước màn hình và nội dung item.
  • Hiệu suất kém với GridView.count và danh sách lớn: Chuyển sang sử dụng GridView.builder để chỉ tạo các item hiển thị trên màn hình.
  • Giao diện lưới không đều: Đảm bảo các item con có kích thước hoặc tỷ lệ khung hình tương đồng, hoặc sử dụng childAspectRatio để kiểm soát tỷ lệ của các ô lưới.
  • Lỗi khi tải ảnh từ mạng: Sử dụng các thư viện quản lý cache ảnh (cached_network_image) và xử lý các trường hợp lỗi tải ảnh.

Kết luận: Làm chủ bố cục lưới với GridView

Trong bài học này, chúng ta đã trang bị cho mình kiến thức về GridView và các biến thể của nó trong Flutter. Từ việc tạo các lưới đơn giản đến việc xây dựng các bố cục phức tạp và tối ưu hóa hiệu suất cho danh sách lớn, GridView mang đến sự linh hoạt tuyệt vời cho việc hiển thị dữ liệu dạng lưới.

Hãy thực hành và thử nghiệm với các thuộc tính khác nhau để hiểu rõ hơn về cách GridView hoạt động và cách bạn có thể tận dụng nó để tạo ra những giao diện người dùng ấn tượng.

Hẹn gặp lại bạn trong những bài học tiếp theo, nơi chúng ta sẽ tiếp tục khám phá những khía cạnh thú vị khác của Flutter! 😊

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 299

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

1 1 357

- vừa được xem lúc

Dart Cheat Sheet - Full bộ "bỏ túi" các syntax trong ngôn ngữ Dart

Dart là một ngôn ngữ mới dùng cho cả Mobile và Web với Flutter Framework, thậm chí dùng cho Backend. Để giúp mọi người dễ dàng nắm bắt ngôn ngữ này hơn, 200lab Education đã tổng hợp thành bộ "bí tịch" dưới đây để tra cứu nhanh, tăng tốc phát triển phần mềm.

0 0 54

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 2: StatefulWidget vs StatelessWidget. Khi nào thì cần sử dụng cái nào?

Lời mở đầu. Ở bài trước, chúng ta đã dừng lại ở một kết thúc mở.

0 0 102

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 4: Lột trần InheritedWidget

Lời mở đầu. Trong đoạn kết của phần 2, chúng ta đã đối mặt với 1 bài toán: Làm thế nào để truyền data từ một widget cha nào đó xuống thẳng widget chắt mà không phải sử dụng constructor để truyền xuống

0 0 72

- vừa được xem lúc

Chinh phục RxDart Flutter trong 3 nốt nhạc. Nốt thứ nhất: Stream và giải thích các thuật ngữ

Lời mở đầu. Mình viết series này với mục đích chia sẻ kiến thức về RxDart trong Flutter.

0 0 80