1. Widget trong Flutter là gì?

Widget là thành phần cơ bản nhất được sử dụng để xây dựng giao diện trong Flutter. Mỗi thành phần trên màn hình như văn bản, hình ảnh, nút bấm, danh sách, khoảng cách hoặc toàn bộ một màn hình đều có thể được biểu diễn bằng Widget.

Thay vì xây dựng giao diện bằng cách điều khiển từng thành phần riêng lẻ, Flutter sử dụng các Widget để mô tả giao diện mà ứng dụng cần hiển thị.

Có thể hiểu đơn giản:

Widget → kết hợp nhiều Widget → tạo thành giao diện → tạo thành màn hình ứng dụng

Ví dụ một màn hình có thể được tạo từ Scaffold, bên trong có AppBar, Column, Text, Image, Button và nhiều Widget khác.

  1. Đặc điểm của Widget

Widget trong Flutter có một số đặc điểm quan trọng:

  • Là thành phần nền tảng để xây dựng UI.
  • Có thể chứa các Widget khác.
  • Có thể được kết hợp và lồng nhau.
  • Có thể tái sử dụng ở nhiều vị trí.
  • Mỗi Widget mô tả một phần giao diện hoặc cách bố trí giao diện.
  • Widget được tổ chức thành một cấu trúc phân cấp gọi là Widget Tree.

Một giao diện Flutter thường không phải là một Widget duy nhất mà là nhiều Widget kết hợp với nhau.

  1. Widget Tree là gì?

Widget Tree là cấu trúc cây thể hiện mối quan hệ giữa các Widget trong giao diện Flutter.

Một Widget có thể là Widget cha và chứa nhiều Widget con. Các Widget con lại có thể tiếp tục chứa những Widget khác.

Ví dụ:

Scaffold
├── AppBar
└── Column
    ├── Text
    ├── Image
    └── ElevatedButton

Trong ví dụ trên, Scaffold là Widget cha lớn, bên trong có AppBar và phần nội dung Column. Column tiếp tục chứa Text, Image và ElevatedButton.

Việc tổ chức giao diện thành Widget Tree giúp Flutter xác định cấu trúc và cách các thành phần giao diện được bố trí với nhau.

  1. Widget có thể lồng nhau

Một đặc điểm quan trọng của Flutter là Widget có thể chứa Widget khác.

Ví dụ:

Scaffold(
  body: Column(
    children: [
      const Text('Sản phẩm'),
      ElevatedButton(
        onPressed: () {},
        child: const Text('Mua hàng'),
      ),
    ],
  ),
)

Trong đoạn code trên, Scaffold chứa Column, Column chứa Text và ElevatedButton, còn ElevatedButton lại chứa một Text.

Đây chính là cách Flutter xây dựng giao diện bằng cách kết hợp các Widget nhỏ thành Widget lớn hơn.

  1. StatelessWidget và StatefulWidget

Trong Flutter, Widget thường được chia thành hai loại quan trọng là: StatelessWidget và StatefulWidget.

StatelessWidget

StatelessWidget là Widget không có State riêng cần thay đổi trong quá trình hoạt động. Widget nhận dữ liệu đầu vào và sử dụng dữ liệu đó để xây dựng giao diện.

Ví dụ:

class ProductTitle extends StatelessWidget {
  const ProductTitle({super.key});

  @override
  Widget build(BuildContext context) {
    return const Text('Sữa Abbott');
  }
}

StatelessWidget thường phù hợp với những thành phần giao diện đơn giản hoặc không cần tự quản lý trạng thái thay đổi.

StatefulWidget

StatefulWidget là Widget có State có thể thay đổi trong quá trình ứng dụng chạy. Ví dụ những thành phần như ô nhập liệu, bộ đếm hoặc giao diện có trạng thái thay đổi có thể cần StatefulWidget.

Phần StatefulWidget vs StatelessWidget là một keyword riêng Anh Huy giao, vì vậy ở phần Fundamentals chỉ cần nắm khái niệm cơ bản này, không cần đi sâu vào vòng đời của State.

  1. Hàm build()

build() là phương thức quan trọng trong Widget. Nó có nhiệm vụ mô tả giao diện mà Widget cần hiển thị.

Ví dụ:

@override
Widget build(BuildContext context) {
  return const Text('Hello Flutter');
}

Giá trị trả về của build() là một Widget.

Do đó có thể hiểu:

build() → trả về Widget → Widget tạo thành giao diện

Trong Flutter, build() có thể được gọi lại khi giao diện cần được xây dựng lại. Vì vậy, phương thức này chủ yếu nên tập trung vào việc mô tả UI.

  1. Một số Widget cơ bản cần biết

Khi học Flutter Widget Fundamentals, cần làm quen với một số Widget thường xuyên xuất hiện trong project:

Text: Dùng để hiển thị văn bản.

const Text('Xin chào Flutter')

Image: Dùng để hiển thị hình ảnh.

Image.asset('images/product.png')

Container: Dùng làm vùng chứa và cho phép thiết lập các thuộc tính như kích thước, màu nền, khoảng cách và đường viền.

Row: Dùng để sắp xếp các Widget theo chiều ngang.

Row → Widget 1 | Widget 2 | Widget 3

Column: Dùng để sắp xếp các Widget theo chiều dọc.

Column
  ↓
Widget 1
  ↓
Widget 2
  ↓
Widget 3

Stack: Dùng để đặt các Widget chồng lên nhau.

Expanded: Dùng để cho một Widget con mở rộng để sử dụng phần không gian còn lại trong Row, Column hoặc Flex.

ListView: Dùng để hiển thị danh sách có thể cuộn.

Scaffold: Cung cấp cấu trúc cơ bản cho một màn hình Flutter, thường kết hợp với AppBar, body, FloatingActionButton, Drawer…

ElevatedButton: Dùng để tạo nút bấm.

TextField: Dùng để cho người dùng nhập dữ liệu.

  1. Widget dùng để xây dựng giao diện như thế nào?

Một giao diện thực tế thường được xây dựng từ nhiều cấp Widget.

Ví dụ màn hình sản phẩm:

Scaffold
└── Column
    ├── Text
    ├── Image
    ├── Text
    └── ElevatedButton

Mỗi Widget đảm nhiệm một phần nhỏ của giao diện. Khi kết hợp chúng lại, Flutter có thể tạo thành một màn hình hoàn chỉnh.

Đây là tư duy quan trọng khi làm Flutter: không xây dựng cả màn hình thành một khối lớn mà chia giao diện thành các Widget nhỏ và kết hợp chúng lại.

  1. Tái sử dụng Widget

Widget có thể được tạo thành các thành phần riêng để sử dụng nhiều lần.

Ví dụ trong ứng dụng bán hàng có thể tạo:

  • ProductItem
  • ProductCard
  • CategoryItem
  • SearchBox
  • AppButton

Sau đó sử dụng lại những Widget này ở nhiều màn hình khác nhau. Việc tái sử dụng Widget giúp:

  • Giảm code trùng lặp.
  • Code dễ đọc hơn.
  • Dễ chỉnh sửa giao diện.
  • Dễ bảo trì project.

Đây là một trong những lợi ích quan trọng của cách xây dựng giao diện bằng Widget.

  1. Flutter xây dựng UI bằng Widget

Flutter sử dụng cách tiếp cận declarative UI, nghĩa là lập trình viên chủ yếu mô tả giao diện cần hiển thị dựa trên dữ liệu và trạng thái hiện tại.

Thay vì phải tự điều khiển từng bước để thay đổi giao diện, lập trình viên xây dựng các Widget mô tả giao diện mong muốn, sau đó Flutter đảm nhiệm quá trình cập nhật giao diện.

Có thể hiểu ngắn gọn:

Dữ liệu/State → Widget mô tả UI → Flutter xây dựng giao diện

Đây là tư duy nền tảng khi làm việc với Flutter.

  1. Những ý chính cần nhớ
- Widget là thành phần cơ bản để xây dựng UI trong Flutter.
- Một giao diện được tạo thành từ nhiều Widget kết hợp với nhau.
- Widget Tree thể hiện cấu trúc cha – con của các Widget.
- Widget có thể lồng nhau và tái sử dụng.
- StatelessWidget và StatefulWidget là hai loại Widget quan trọng.
- build() dùng để mô tả giao diện của Widget.
- Cần nắm các Widget cơ bản như Text, Image, Container, Row, Column, Stack, Expanded, ListView, Scaffold, Button, TextField.
- Flutter sử dụng cách tiếp cận declarative UI để xây dựng giao diện.
- Trong project thực tế nên chia giao diện thành các Widget nhỏ để dễ quản lý và tái sử dụng.
  1. Kết luận

Flutter Widget Fundamentals là kiến thức nền tảng để bắt đầu làm giao diện bằng Flutter. Cốt lõi của phần này là hiểu Widget là gì, Widget Tree hoạt động như thế nào, cách các Widget lồng nhau và những Widget cơ bản dùng để xây dựng giao diện.

Sau khi nắm được phần Fundamentals, có thể tiếp tục học sâu hơn về StatelessWidget vs StatefulWidget, sau đó đến Flutter Layout & Responsive UI và các keyword tiếp theo.

 

Bài viết khác

BÀI 5: TÌM HIỂU CHUYÊN SÂU VỀ LANGUAGE SWITCHING TRONG FLUTTER

1. Language Switching là gì? Trong một ứng dụng hỗ trợ nhiều ngôn ngữ, việc có sẵn các bản dịch chưa đủ để tạo ra trải nghiệm đa ngôn ngữ hoàn chỉnh. Ứng dụng còn cần xác định ngôn ngữ nào sẽ được sử dụng và cho phép thay đổi ngôn ngữ khi cần thiết. […]

TÌM HIỂU CHUYÊN SÂU VỀ UTC & LOCAL TIME CONVERSION TRONG FLUTTER

1. UTC & Local Time Conversion là gì? Trong một ứng dụng Flutter, thời gian xuất hiện ở rất nhiều chức năng như ngày tạo tài khoản, thời gian đặt hàng, lịch sử giao dịch, lịch hẹn, thời gian gửi thông báo và thời hạn của chương trình khuyến mãi. Khi ứng dụng chỉ chạy […]

TÌM HIỂU CHUYÊN SÂU VỀ DATE / NUMBER / CURRENCY FORMATTING TRONG FLUTTER

1. Date / Number / Currency Formatting là gì? Trong một ứng dụng Flutter, dữ liệu thường được lưu trữ và xử lý dưới dạng số, ngày giờ hoặc các kiểu dữ liệu có cấu trúc. Tuy nhiên, dữ liệu dùng để tính toán không nhất thiết giống với cách dữ liệu được hiển thị […]

TÌM HIỂU CHUYÊN SÂU VỀ LOCALIZATION (l10n) TRONG FLUTTER

1. Localization (l10n) là gì? Khi một ứng dụng được sử dụng ở nhiều quốc gia, sự khác biệt không chỉ nằm ở ngôn ngữ mà còn ở cách người dùng đọc ngày tháng, số, tiền tệ, đơn vị đo lường và các thông tin trên giao diện. Ví dụ, một ứng dụng bán hàng […]

TÌM HIỂU CHUYÊN SÂU VỀ INTERNATIONALIZATION (i18n) TRONG FLUTTER

1. Internationalization (i18n) là gì? Trong quá trình phát triển ứng dụng, lập trình viên thường xây dựng giao diện bằng một ngôn ngữ ban đầu, chẳng hạn như tiếng Việt. Khi ứng dụng được sử dụng bởi người dùng ở nhiều quốc gia, việc chỉ hỗ trợ một ngôn ngữ có thể khiến người […]

TÌM HIỂU CHUYÊN SÂU VỀ APP RELEASE & DEPLOYMENT TRONG FLUTTER

1. App Release & Deployment là gì? Trong quá trình phát triển ứng dụng Flutter, sau khi hoàn thành các chức năng, lập trình viên cần đưa ứng dụng đến người dùng thực tế. Ví dụ, một nhóm đã xây dựng xong ứng dụng bán hàng với những chức năng như đăng nhập, xem sản […]

Leave a Reply

Your email address will not be published. Required fields are marked *