Bài 4. Widget và cây widget

Trong Flutter, giao diện là một cây widget lồng nhau. Bài này giải thích widget là gì, StatelessWidget, phương thức build, BuildContext và các widget cơ bản nhất.

50 phútCơ bản
Bạn sẽ học được
  • Hiểu triết lý “mọi thứ là widget”
  • Viết StatelessWidget riêng
  • Dùng Text, Icon, Image, Container, ElevatedButton
  • Hiểu Material 3 và ThemeData
Thuật ngữ cần biết
Widget
Mô tả bất biến của một phần giao diện.
build()
Phương thức trả về cây widget con.
BuildContext
Vị trí của widget trong cây, dùng để tra theme, điều hướng.
Material 3
Hệ thiết kế mặc định của Flutter.

Khái niệm và lý thuyết

Widget là bản mô tả giao diện, không phải đối tượng vẽ trực tiếp. Flutter giữ ba cây: Widget (mô tả, tạo lại thường xuyên, rất rẻ), Element (gắn widget vào vị trí, tồn tại lâu) và RenderObject (đo, bố trí, vẽ). Khi dữ liệu đổi, Flutter gọi lại build, so sánh cây mới với cũ và chỉ cập nhật phần thay đổi.

Lập trình giao diện theo kiểu khai báo (declarative): bạn mô tả giao diện ứng với trạng thái hiện tại, UI = f(state), thay vì ra lệnh sửa từng thành phần như Android XML truyền thống.

StatelessWidget tự viết

class TheKhoaHoc extends StatelessWidget {
  const TheKhoaHoc({super.key, required this.ten, required this.soBai});
  final String ten;
  final int soBai;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Card(
      child: ListTile(
        leading: const Icon(Icons.school),
        title: Text(ten, style: theme.textTheme.titleMedium),
        subtitle: Text('$soBai bài học'),
        trailing: const Icon(Icons.chevron_right),
      ),
    );
  }
}

Widget cơ bản

WidgetCông dụng
TextHiển thị chữ, định dạng bằng TextStyle
IconBiểu tượng Material (Icons.*)
Image.asset / Image.networkẢnh trong dự án / từ Internet
ContainerHộp có màu, viền, padding, kích thước
ElevatedButton, FilledButton, TextButtonCác loại nút
ScaffoldKhung màn hình: AppBar, body, FloatingActionButton

Theme Material 3

MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
  ),
  darkTheme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
        seedColor: Colors.green, brightness: Brightness.dark),
  ),
  home: const TrangChu(),
);

Chỉ cần một màu gốc, Flutter sinh cả bảng màu hài hòa cho chế độ sáng và tối.

Mẹo hay

Đặt const trước widget không đổi (ví dụ const Icon(Icons.school)); trình phân tích của VS Code sẽ nhắc bạn.

Lưu ý

Hàm build có thể chạy rất nhiều lần. Không đặt thao tác nặng (gọi API, đọc tệp) trong build.

Thực hành
  1. Tạo widget TheSinhVien hiển thị ảnh đại diện, tên, lớp.
  2. Dựng màn hình Scaffold có AppBar, nút FloatingActionButton hiện SnackBar khi bấm.
  3. Đổi màu gốc của theme và bật darkTheme.
  4. Thêm ảnh vào thư mục assets, khai báo trong pubspec.yaml và hiển thị.
Tóm tắt bài học
  • Giao diện là cây widget, mô tả theo kiểu khai báo.
  • StatelessWidget dùng cho phần không có trạng thái.
  • Widget, Element, RenderObject chia việc mô tả, quản lý, vẽ.
  • Material 3 tạo theme từ một màu gốc.