MaterialApp: định nghĩa và cách thiết lập widget gốc

Tác giả: IT Sectr Đã đăng: 2026-07-02 Thời gian đọc: 9 phút

MaterialApp là widget gốc trong Flutter dùng để cấu hình Material Design cho toàn bộ ứng dụng. Nó cung cấp cấu hình tập trung cho định tuyến, thiết lập chủ đề, bản địa hóa và điều hướng, tự động thêm các thành phần như Navigator, Theme và MediaQuery vào Widget Tree. Theo Tài liệu tham khảo API Flutter, 2025, MaterialApp là widget bắt buộc cho bất kỳ ứng dụng Flutter nào sử dụng Material Design và thiết lập các cấu hình toàn cục có sẵn trong toàn bộ cây widget.

Những điểm chính

  • MaterialApp — widget gốc cấu hình Material Design, định tuyến và thiết lập chủ đề cho ứng dụng Flutter.
  • Thiết lập chủ đề qua tham số theme và darkTheme xác định bảng màu, phông chữ và kiểu dáng cho toàn bộ ứng dụng.
  • Định tuyến qua routes và onGenerateRoute cung cấp điều hướng giữa các màn hình ứng dụng.
  • Bản địa hóa qua localizationsDelegates và supportedLocales thêm hỗ trợ đa ngôn ngữ.
  • InheritedWidget lồng nhau — MaterialApp tự động thêm Theme, MediaQuery, Navigator và Localizations vào cây.

MaterialApp trong Flutter là gì?

MaterialApp là một widget bao bọc khởi tạo Material Design trong ứng dụng Flutter. Nó là gốc của Widget Tree và cung cấp cho các widget con quyền truy cập vào các dịch vụ hệ thống: điều hướng, chủ đề, truy vấn phương tiện và bản địa hóa. Nếu không có MaterialApp, ứng dụng sẽ không có kiểu Material tiêu chuẩn và không thể sử dụng các widget như Scaffold, AppBar, FloatingActionButton và BottomNavigationBar.

MaterialApp thêm gì vào Widget Tree

Khi sử dụng MaterialApp, Flutter tự động thêm một số widget chính vào gốc cây: Navigator (ngăn xếp màn hình để điều hướng), Theme (bảng màu và kiểu dáng), MediaQuery (thông tin thiết bị), Localizations (chuỗi đã bản địa hóa), Directionality (hướng văn bản). Các widget này được triển khai dưới dạng InheritedWidget và có thể truy cập qua BuildContext ở bất kỳ đâu trong ứng dụng.

Sử dụng cơ bản

Cấu hình tối thiểu của MaterialApp chỉ yêu cầu tham số home — widget hiển thị trên màn hình chính. Flutter tự động bọc home trong Scaffold nếu nó chưa phải là Scaffold, thông qua cơ chế WidgetsBinding. Khi bạn khởi chạy ứng dụng với runApp(MaterialApp(home: MyHomePage())), Flutter tạo một Widget Tree gốc với MaterialApp làm gốc.

dart
void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "My Application",
      theme: ThemeData(
        primarySwatch: Colors.blue,
        fontFamily: "Roboto",
      ),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

Trong ví dụ này, MaterialApp cấu hình chủ đề cơ bản (sáng và tối), tiêu đề và màn hình chính. Tham số title được sử dụng cho tiêu đề cửa sổ (trên máy tính) và cho khả năng truy cập. Các tham số theme và darkTheme xác định giao diện của ứng dụng trong các chế độ khác nhau.

Cấu trúc và tham số của MaterialApp

MaterialApp chấp nhận hơn 30 tham số, được chia thành các danh mục: cài đặt Material Design, định tuyến, thiết lập chủ đề, bản địa hóa, hành vi lỗi và cài đặt dành riêng cho nền tảng. Biết các tham số chính cho phép bạn cấu hình ứng dụng một cách linh hoạt mà không cần viết thêm mã.

Các tham số cấu hình chính

Tham số title đặt tên ứng dụng cho tiêu đề cửa sổ và khả năng truy cập. color xác định màu ứng dụng cho bộ chuyển đổi tác vụ trên Android. debugShowCheckedModeBanner ẩn biểu ngữ chế độ gỡ lỗi trong bản dựng phát hành. showPerformanceOverlay bật lớp phủ với thông tin hiệu suất. supportDarkTheme cho biết ứng dụng có hỗ trợ chủ đề tối hay không.

Tham số dành riêng cho nền tảng

MaterialApp cung cấp các tham số để cấu hình hành vi trên các nền tảng khác nhau: restorationScopeId để bảo toàn trạng thái ứng dụng khi khởi động lại trên Android, scrollBehavior để cấu hình hành vi cuộn trên các HĐH khác nhau, useMaterial3 để bật Material 3 (Material You). Material 3 thêm màu sắc động, thành phần mới và kiểu dáng cập nhật.

Tham sốLoạiMục đích
titleStringTiêu đề cửa sổ ứng dụng
themeThemeDataCấu hình chủ đề sáng
darkThemeThemeDataCấu hình chủ đề tối
homeWidgetMàn hình chính của ứng dụng
routesMap<String, WidgetBuilder>Bản đồ các route có tên
localeLocaleLocale bắt buộc của ứng dụng

Thiết lập chủ đề với theme và darkTheme

Thiết lập chủ đề là một trong những tham số chính của MaterialApp. Tham số theme chấp nhận một đối tượng ThemeData xác định bảng màu, kiểu chữ, hình dạng thành phần và biểu tượng cho chủ đề sáng. Tham số darkTheme là cấu hình tương đương cho chủ đề tối. Flutter tự động chuyển đổi chủ đề dựa trên cài đặt hệ thống của thiết bị.

ThemeData: bảng màu

ThemeData bao gồm primarySwatch (màu chính), colorScheme (bảng màu mở rộng Material 3), brightness (sáng hoặc tối), fontFamily (phông chữ mặc định), textTheme (kiểu văn bản), cardTheme, appBarTheme, buttonTheme và hàng chục tham số khác để tùy chỉnh các thành phần cụ thể. Sử dụng colorScheme cho Material 3 và primarySwatch cho Material 2.

Màu sắc động Material 3

Material 3 (Material You) hỗ trợ màu sắc động, được trích xuất từ hình nền thiết bị trên Android 12+. Để kích hoạt, đặt useMaterial3: true và sử dụng colorScheme.fromSeed hoặc colorScheme.fromImageProvider. Màu sắc động tự động tạo ra một bảng màu hài hòa gồm 5 tông: primary, secondary, tertiary, neutral và neutralVariant.

Truy cập chủ đề trong widget

Bất kỳ widget nào cũng có thể truy cập chủ đề hiện tại qua Theme.of(context). Theme.of trả về một đối tượng ThemeData từ đó bạn có thể lấy colors, textTheme và các tham số khác. Để đăng ký thay đổi chủ đề (ví dụ: khi chuyển đổi giữa chế độ sáng và tối), hãy sử dụng ngữ cảnh bên trong phương thức build — Flutter sẽ tự động xây dựng lại widget khi chủ đề thay đổi.

dart
Container(
  color: Theme.of(context).colorScheme.primary,
  child: Text(
    "Themed text example",
    style: Theme.of(context).textTheme.headlineMedium,
  ),
)

Trong ví dụ này, Theme.of(context) lấy chủ đề hiện tại từ MaterialApp gần nhất. Màu nền và kiểu văn bản tự động khớp với chủ đề hiện tại (sáng hoặc tối). Khi chủ đề chuyển đổi, Container và Text sẽ được xây dựng lại với các giá trị mới từ ThemeData đã cập nhật.

Định tuyến và điều hướng trong MaterialApp

MaterialApp tích hợp Navigator — một bộ điều hướng dựa trên ngăn xếp quản lý chuyển tiếp giữa các màn hình. Các tham số initialRoute, routes và onGenerateRoute xác định cách Flutter xử lý điều hướng. Navigator.push và Navigator.pushReplacement cho phép chuyển đổi màn hình theo chương trình, trong khi Navigator.pop cho phép quay lại.

Route có tên (routes)

Tham số routes chấp nhận Map<String, WidgetBuilder>, trong đó khóa là tên route (chuỗi) và giá trị là hàm tạo widget cho màn hình đó. Các route có tên thuận tiện cho điều hướng tĩnh: '/' (route gốc) thường tương ứng với home, '/settings', '/profile' — các màn hình khác. Navigator.pushNamed(context, '/settings') điều hướng đến màn hình cài đặt.

Tạo route (onGenerateRoute)

onGenerateRoute là một hàm được gọi khi không tìm thấy route trong routes. Nó chấp nhận RouteSettings và trả về MaterialPageRoute. Cách tiếp cận này hữu ích cho điều hướng động khi các route phụ thuộc vào dữ liệu (ví dụ: /user/42). onGenerateRoute phân tích tên route, trích xuất tham số và tạo màn hình thích hợp.

Liên kết sâu và định tuyến có tên

Để hỗ trợ liên kết sâu (deep links), hãy sử dụng các tham số onGenerateInitialRoute và onGenerateRoute cùng nhau. Liên kết sâu cho phép mở một màn hình cụ thể của ứng dụng qua URL (ví dụ: https://example.com/promo). Flutter xử lý liên kết sâu trên Android (qua intent filters) và iOS (qua universal links) và chuyển đường dẫn đến onGenerateRoute.

dart
MaterialApp(
  initialRoute: "/",
  routes: {
    "/": (context) => const HomePage(),
    "/settings": (context) => const SettingsPage(),
  },
  onGenerateRoute: (settings) {
    if (settings.name?.startsWith("/user/") == true) {
      final userId = settings.name!.split("/").last;
      return MaterialPageRoute(
        builder: (_) => UserPage(userId: userId),
      );
    }
    return null;
  },
)

Trong ví dụ này, onGenerateRoute xử lý các route động như /user/42. Nếu route không được tìm thấy trong các route tĩnh và không khớp với mẫu động, Flutter hiển thị trang lỗi, có thể tùy chỉnh qua onUnknownRoute.

Bản địa hóa và quốc tế hóa

MaterialApp cung cấp hỗ trợ bản địa hóa tích hợp qua các tham số localizationsDelegates và supportedLocales. LocalizationsDelegates tải các chuỗi đã bản địa hóa, và supportedLocales xác định ngôn ngữ mà ứng dụng hỗ trợ. Flutter tự động phát hiện ngôn ngữ thiết bị và tải các tài nguyên đã bản địa hóa tương ứng.

Cấu hình supportedLocales và localizationsDelegates

Tham số supportedLocales chấp nhận danh sách Locale mà ứng dụng hỗ trợ: [const Locale('en'), const Locale('ru'), const Locale('de')]. localizationsDelegates là danh sách các delegate tải chuỗi đã bản địa hóa. Đối với Material Design, hãy thêm GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate và GlobalCupertinoLocalizations.delegate.

Bản địa hóa chuỗi ứng dụng

Để bản địa hóa chuỗi của riêng bạn, hãy sử dụng lớp AppLocalizations, được tạo qua flutter_localizations hoặc gói intl. AppLocalizations cung cấp các phương thức tĩnh để truy cập chuỗi đã bản địa hóa: AppLocalizations.of(context)!.helloMessage. MaterialApp tự động chuyển Localizations vào Widget Tree, làm cho chúng có thể truy cập qua ngữ cảnh.

  • flutter_localizations — gói chính thức để bản địa hóa widget Material và chuỗi hệ thống.
  • intl — gói quốc tế hóa: định dạng số, ngày tháng, tiền tệ và số nhiều.
  • Tệp ARB — định dạng lưu trữ chuỗi đã bản địa hóa, được sử dụng bởi flutter_localizations và intl.

MaterialApp vs CupertinoApp vs WidgetsApp

Flutter cung cấp ba widget gốc cho các nền tảng khác nhau: MaterialApp (Material Design cho Android và web), CupertinoApp (kiểu iOS) và WidgetsApp (widget cơ bản không có kiểu dáng). Việc chọn widget gốc quyết định giao diện của toàn bộ ứng dụng và sự sẵn có của các thành phần dành riêng cho nền tảng.

MaterialApp: lựa chọn phổ quát

MaterialApp phù hợp với hầu hết các ứng dụng nhờ hỗ trợ Material Design, hiển thị đẹp trên Android, web và máy tính để bàn. Material Design cung cấp một thư viện thành phần phong phú: Scaffold, AppBar, BottomNavigationBar, Drawer, SnackBar, Dialog và nhiều thành phần khác. MaterialApp cũng hỗ trợ Material 3 với màu sắc động.

CupertinoApp: kiểu iOS

CupertinoApp sử dụng Cupertino Design, tuân theo Nguyên tắc Giao diện Người dùng của Apple. Nó cung cấp CupertinoPageScaffold, CupertinoNavigationBar, CupertinoTabBar và các thành phần kiểu iOS khác. Sử dụng CupertinoApp cho ứng dụng iOS hoặc ứng dụng theo kiểu Apple trên tất cả các nền tảng.

WidgetsApp: gốc tối thiểu

WidgetsApp là widget gốc cơ bản không có kiểu dáng. Nó thêm Navigator, MediaQuery và Localizations nhưng không cung cấp chủ đề hoặc thành phần Material/Cupertino. WidgetsApp phù hợp cho các hệ thống thiết kế tùy chỉnh, trò chơi hoặc ứng dụng có kiểu dáng riêng nơi Material hoặc Cupertino là quá mức cần thiết.

Widget gốcHệ thống thiết kếKhi nào sử dụng
MaterialAppMaterial Design (Google)Android, web, máy tính để bàn, ứng dụng đa nền tảng
CupertinoAppCupertino (Apple HIG)Ứng dụng iOS, kiểu Apple trên tất cả nền tảng
WidgetsAppKhông kiểu dángThiết kế tùy chỉnh, trò chơi, hệ thống thiết kế riêng

Câu hỏi thường gặp

MaterialApp có bắt buộc trong ứng dụng Flutter không?

Không bắt buộc — bạn có thể sử dụng CupertinoApp cho kiểu iOS hoặc WidgetsApp cho thiết kế tùy chỉnh. MaterialApp bắt buộc nếu bạn sử dụng widget Material: Scaffold, AppBar, FloatingActionButton và các widget khác.

Làm thế nào để chuyển đổi chủ đề trong MaterialApp?

Sử dụng tham số theme (chủ đề sáng) và darkTheme (chủ đề tối). Flutter tự động chuyển đổi chủ đề dựa trên cài đặt hệ thống. Để chuyển đổi bắt buộc, sử dụng WidgetsBinding.instance.platformDispatcher.platformBrightness.

Có thể sử dụng MaterialApp mà không có Material 3 không?

Có, theo mặc định useMaterial3 là false và MaterialApp sử dụng Material 2. Để kích hoạt Material 3, đặt useMaterial3: true và sử dụng colorScheme từ ColorScheme.fromSeed.

Làm thế nào để thêm trang lỗi 404 tùy chỉnh?

Sử dụng tham số onUnknownRoute, chấp nhận RouteSettings và trả về MaterialPageRoute. Nếu cả routes và onGenerateRoute đều không xử lý route, onUnknownRoute được gọi — hãy trả về một trang có thông báo lỗi.

Điều gì xảy ra nếu không chỉ định home trong MaterialApp?

Nếu tham số home không được chỉ định và không có routes, Flutter sẽ ném ngoại lệ khi khởi động. Bạn phải chỉ định ít nhất một trong các mục sau: home, routes với route '/' hoặc initialRoute.

Tổng kết

  • MaterialApp là widget gốc của Flutter để cấu hình Material Design, định tuyến, thiết lập chủ đề và bản địa hóa ứng dụng.
  • Tham số chính: title, theme, darkTheme, home, routes, locale và useMaterial3 cho Material 3.
  • Thiết lập chủ đề qua ThemeData xác định màu sắc, phông chữ và kiểu dáng có thể truy cập qua Theme.of(context) trong bất kỳ widget nào.
  • Định tuyến qua routes (route tĩnh) và onGenerateRoute (route động) cung cấp điều hướng linh hoạt.
  • Bản địa hóa qua supportedLocales và localizationsDelegates thêm hỗ trợ đa ngôn ngữ.
  • MaterialApp tự động nhúng Navigator, Theme, MediaQuery, Localizations và Directionality vào Widget Tree.
  • Thay thế: CupertinoApp (kiểu iOS) và WidgetsApp (thiết kế tùy chỉnh) cho ứng dụng không có Material Design.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm