
Chào mừng các bạn đến với buổi giải phẫu một trong những "biển hiệu" quan trọng nhất của ứng dụng di động: Banner trong Flutter! Hãy hình dung thế này, ứng dụng của bạn là một cửa hàng sầm uất. Đôi khi bạn cần một cái loa phóng thanh để thông báo "Khuyến mãi cực SỐC!" hoặc một tấm biển cảnh báo "Cửa hàng đang bảo trì, quý khách quay lại sau 5 phút." Trong thế giới Flutter, Banner chính là những công cụ "loa phóng thanh" và "biển hiệu" số đó.
1. Banner Là Gì? Để Làm Gì?
"Banner" trong Flutter, đặc biệt là MaterialBanner, không phải là những tấm quảng cáo giăng đầy đường phố mà bạn thường thấy trên web (dù có những widget tùy chỉnh cũng có thể làm điều đó). Thay vào đó, nó là một loại thông báo tạm thời, không chiếm quá nhiều diện tích màn hình, thường xuất hiện ở rìa trên của ứng dụng để truyền tải những thông điệp quan trọng hoặc ngữ cảnh cụ thể đến người dùng.
Mục đích chính của Banner:
- Cảnh báo quan trọng: "Mất kết nối Internet!", "Phiên đăng nhập của bạn đã hết hạn.", "Lỗi tải dữ liệu."
- Nhắc nhở nhẹ nhàng: "Bạn có 3 tin nhắn mới.", "Hãy cập nhật hồ sơ để nhận ưu đãi."
- Thông báo tính năng mới: "Khám phá tính năng 'Chế độ tối' vừa ra mắt!"
- Xác nhận hành động (ít phổ biến hơn
SnackBar): Mặc dùSnackBarthường được dùng cho xác nhận, đôi khiMaterialBannercũng có thể báo "Đã lưu thay đổi thành công" nếu thông điệp cần nổi bật hơn.
Điểm khác biệt lớn nhất giữa MaterialBanner và SnackBar (một "loa phóng thanh" khác) là MaterialBanner thường nằm cố định ở trên cùng màn hình cho đến khi được đóng thủ công, và nó có thể chứa nhiều hành động hơn, mang thông điệp "nghiêm túc" hơn một chút. Trong khi SnackBar thường tự động biến mất và dùng cho các thông báo ngắn gọn, ít quan trọng hơn.

2. Code Ví Dụ Minh Họa: MaterialBanner - Người Gác Cổng Thông Báo
Trong Flutter, MaterialBanner là widget "chính chủ" để tạo ra các thông báo banner theo phong cách Material Design. Để hiển thị nó, chúng ta sẽ cần đến ScaffoldMessenger, một "người quản lý" các thông báo cho Scaffold (khung sườn chính của màn hình).
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Banner Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isBannerShowing = false;
void _showMaterialBanner(BuildContext context) {
if (_isBannerShowing) return; // Tránh hiển thị nhiều banner cùng lúc
ScaffoldMessenger.of(context).showMaterialBanner(
MaterialBanner(
content: const Text(
'Ồ không! Kết nối Internet của bạn đã bị ngắt.',
style: TextStyle(color: Colors.white),
),
leading: const Icon(Icons.signal_wifi_off, color: Colors.white),
backgroundColor: Colors.redAccent,
actions: [
TextButton(
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentMaterialBanner();
setState(() {
_isBannerShowing = false;
});
// Thường thì ở đây bạn sẽ thử kết nối lại hoặc navigate
print('Người dùng đã chọn Thử lại');
},
child: const Text('THỬ LẠI', style: TextStyle(color: Colors.white)),
),
TextButton(
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentMaterialBanner();
setState(() {
_isBannerShowing = false;
});
print('Người dùng đã chọn Bỏ qua');
},
child: const Text('BỎ QUA', style: TextStyle(color: Colors.white)),
),
],
),
);
setState(() {
_isBannerShowing = true;
});
}
void _hideMaterialBanner(BuildContext context) {
if (!_isBannerShowing) return;
ScaffoldMessenger.of(context).hideCurrentMaterialBanner();
setState(() {
_isBannerShowing = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Demo MaterialBanner'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Nhấn nút để hiển thị/ẩn Banner:',
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => _showMaterialBanner(context),
child: const Text('Hiển thị Cảnh báo'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () => _hideMaterialBanner(context),
child: const Text('Ẩn Cảnh báo'),
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
// Ví dụ một banner khác, ít quan trọng hơn
ScaffoldMessenger.of(context).showMaterialBanner(
MaterialBanner(
content: const Text('Chào mừng bạn đến với tính năng mới!'),
leading: const Icon(Icons.info_outline),
backgroundColor: Colors.lightGreen,
actions: [
TextButton(
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentMaterialBanner();
},
child: const Text('ĐÓNG'),
),
],
),
);
},
child: const Text('Hiển thị Thông báo khác'),
),
],
),
),
);
}
}
Trong ví dụ trên:
- Chúng ta sử dụng
ScaffoldMessenger.of(context).showMaterialBanner()để hiển thị banner. MaterialBannernhận vàocontent(nội dung text),leading(một icon ở đầu banner),backgroundColor(màu nền), và quan trọng nhất làactions(danh sách các nút hành động mà người dùng có thể tương tác).- Để ẩn banner, chúng ta gọi
ScaffoldMessenger.of(context).hideCurrentMaterialBanner(). Thường thì hành động này sẽ được gắn vào một trong các nútactionscủa banner.
3. Mẹo (Best Practices) Để Dùng Banner Hiệu Quả
Giống như một người bán hàng tài ba biết khi nào nên nói và khi nào nên im lặng, việc sử dụng Banner cũng cần sự tinh tế:
- "Đừng la hét quá nhiều!" (Không lạm dụng): Banner rất nổi bật, nhưng nếu bạn dùng nó cho mọi thứ, người dùng sẽ nhanh chóng bỏ qua hoặc khó chịu. Chỉ dùng cho các thông điệp thực sự quan trọng, không thể bỏ qua.
- "Thông điệp ngắn gọn, súc tích" (Clear & Concise): Banner không phải là nơi để kể một câu chuyện dài. Hãy đi thẳng vào vấn đề, dùng ít từ nhất có thể mà vẫn truyền tải đủ ý.
- "Màu sắc nói lên tất cả" (Contextual Colors): Màu đỏ cho lỗi nguy hiểm, màu vàng cho cảnh báo, màu xanh lá cho thành công hoặc thông tin tích cực. Hãy để màu sắc "nói hộ" mức độ quan trọng của thông điệp.
- "Luôn có lối thoát" (Provide Dismissal): Trừ khi là trường hợp cực kỳ khẩn cấp yêu cầu người dùng phải hành động, hãy luôn cung cấp một nút để người dùng có thể đóng banner. Điều này giúp họ cảm thấy có quyền kiểm soát và không bị "mắc kẹt".
- "Hành động cụ thể" (Actionable): Nếu banner cảnh báo lỗi, hãy cung cấp nút "Thử lại" hoặc "Xem chi tiết". Nếu là thông báo tính năng mới, hãy có nút "Khám phá ngay". Đừng chỉ thông báo suông.
- "Mỗi lần một, đừng chen chúc" (One at a time):
ScaffoldMessengerchỉ cho phép mộtMaterialBannerđược hiển thị tại một thời điểm. Nếu bạn gọishowMaterialBannerkhi đã có một banner khác đang hiển thị, banner cũ sẽ tự động bị ẩn đi để nhường chỗ cho banner mới. Hãy tận dụng điều này để quản lý luồng thông báo.
4. Ứng Dụng Thực Tế
Bạn sẽ thấy Banner ở khắp mọi nơi trong các ứng dụng hàng ngày, đôi khi bạn còn không để ý nó là một "Banner" mà chỉ coi đó là một phần tự nhiên của trải nghiệm:
- Ứng dụng ngân hàng/tài chính: Khi hệ thống đang bảo trì, bạn sẽ thấy một banner ở đầu màn hình thông báo "Hệ thống đang được nâng cấp, vui lòng thử lại sau X phút." Hoặc cảnh báo về một giao dịch đáng ngờ.
- Ứng dụng mạng xã hội (Facebook, Instagram): Thông báo "Bạn có X tin nhắn/thông báo mới" khi bạn không ở tab thông báo. Hoặc nhắc nhở "Cập nhật ảnh đại diện của bạn để kết nối tốt hơn."
- Ứng dụng mua sắm (Shopee, Lazada, Tiki): Đôi khi sẽ có banner nhỏ ở trên cùng thông báo "Miễn phí vận chuyển cho đơn hàng trên X VNĐ" hoặc "Flash Sale chỉ còn Y phút!"
- Gmail/Google Drive: Cảnh báo khi dung lượng lưu trữ của bạn sắp đầy, hoặc thông báo về một tính năng bảo mật mới đã được kích hoạt.
- Hệ điều hành Android/iOS (trong một số ứng dụng): Khi một ứng dụng yêu cầu quyền truy cập vào vị trí hoặc micro, đôi khi sẽ có một banner giải thích lý do trước khi bật popup yêu cầu quyền chính thức.
Như vậy, Banner không chỉ là một widget đơn thuần, nó là một công cụ truyền thông mạnh mẽ, giúp ứng dụng của bạn "nói chuyện" một cách hiệu quả và đúng lúc với người dùng. Hãy sử dụng nó một cách thông minh để nâng cao trải nghiệm người dùng và truyền tải thông điệp của bạn đến đúng đối tượng, đúng thời điểm!
Thuộc Series: Flutter
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!