
Chào mừng các bạn đến với buổi học hôm nay về một khái niệm UI cực kỳ 'nghệ' trong Flutter: Backdrop. Hãy hình dung ứng dụng của bạn như một sân khấu kịch hoành tráng. Thông thường, khán giả chỉ thấy màn trình diễn chính ở phía trước. Nhưng đôi khi, để màn trình diễn đó mượt mà và hiệu quả, chúng ta cần một khu vực 'hậu trường' tinh vi, nơi mọi thứ được điều khiển, sắp đặt. Backdrop chính là cái 'hậu trường' đó, nhưng được thiết kế để khán giả có thể 'hé mở' và tương tác một cách duyên dáng.
1. Backdrop là gì và dùng để làm gì?
Trong thế giới Flutter, Backdrop là một kiểu thiết kế giao diện người dùng (UI) theo chuẩn Material Design, cho phép bạn chia màn hình thành hai lớp rõ rệt: một lớp phía sau (back layer) và một lớp phía trước (front layer). Tưởng tượng như bạn có một tấm rèm hai mặt vậy:
- Lớp phía sau (Back Layer): Đây thường là nơi chứa các điều khiển, tùy chọn, bộ lọc, cài đặt, hoặc các hành động phụ trợ. Nó giống như bảng điều khiển của đạo diễn sân khấu vậy – không phải lúc nào cũng hiển thị, nhưng cực kỳ quan trọng để định hình màn trình diễn chính.
- Lớp phía trước (Front Layer): Đây là nơi hiển thị nội dung chính của ứng dụng, nơi người dùng tương tác nhiều nhất. Đây chính là 'màn trình diễn' mà khán giả tập trung vào. Khi lớp phía trước được kéo xuống, lớp phía sau sẽ lộ ra. Khi kéo lên, nó che đi lớp phía sau và trở lại làm tâm điểm.
Vậy dùng để làm gì? Backdrop sinh ra để giải quyết bài toán về không gian UI và sự rõ ràng. Thay vì nhồi nhét mọi nút bấm, bộ lọc vào một màn hình duy nhất gây rối mắt, Backdrop cho phép bạn 'giấu' những công cụ phụ trợ này đi một cách thanh lịch. Khi cần, người dùng chỉ việc 'lật' màn hình chính xuống, thao tác, rồi 'đóng' lại để quay về nội dung. Nó giúp duy trì sự tập trung vào nội dung chính mà vẫn cung cấp quyền truy cập nhanh chóng đến các tùy chọn quan trọng, tạo ra trải nghiệm người dùng mượt mà và trực quan hơn.

2. Code Ví Dụ Minh Hoạ: Sân Khấu Đổi Màu
Để dễ hình dung, chúng ta sẽ xây dựng một ứng dụng nhỏ nơi lớp phía sau cho phép bạn chọn màu, và lớp phía trước sẽ thay đổi màu nền theo lựa chọn đó. Chúng ta sẽ sử dụng package backdrop (thêm backdrop: ^0.8.0 vào pubspec.yaml của bạn).
import 'package:flutter/material.dart';
import 'package:backdrop/backdrop.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Backdrop Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const BackdropScreen(),
);
}
}
class BackdropScreen extends StatefulWidget {
const BackdropScreen({super.key});
@override
State<BackdropScreen> createState() => _BackdropScreenState();
}
class _BackdropScreenState extends State<BackdropScreen> {
Color _selectedColor = Colors.blue;
String _selectedColorName = 'Blue';
@override
Widget build(BuildContext context) {
return BackdropScaffold(
appBar: BackdropAppBar(
title: Text('Sân Khấu Backdrop'),
actions: const <Widget>[
BackdropToggleButton(icon: AnimatedIcons.list_view),
],
),
backLayer: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildColorOption(Colors.red, 'Red'),
_buildColorOption(Colors.green, 'Green'),
_buildColorOption(Colors.purple, 'Purple'),
_buildColorOption(Colors.orange, 'Orange'),
],
),
),
frontLayer: Center(
child: Container(
width: double.infinity,
height: double.infinity,
color: _selectedColor,
alignment: Alignment.center,
child: Text(
'Màu nền hiện tại: $_selectedColorName',
style: const TextStyle(fontSize: 24, color: Colors.white),
),
),
),
);
}
Widget _buildColorOption(Color color, String name) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
setState(() {
_selectedColor = color;
_selectedColorName = name;
});
// Tự động đóng back layer sau khi chọn màu
Backdrop.of(context).revealBackLayer();
},
style: ElevatedButton.styleFrom(
backgroundColor: color,
foregroundColor: Colors.white,
minimumSize: const Size(150, 50),
),
child: Text(name, style: const TextStyle(fontSize: 18)),
),
);
}
}
Giải thích code:
BackdropScaffold: Đây là widget chính cung cấp cấu trúc cho Backdrop. Nó đòi hỏiappBar,backLayer, vàfrontLayer.BackdropAppBar: MộtAppBarđặc biệt choBackdropScaffoldhỗ trợ nútBackdropToggleButton.BackdropToggleButton: Nút này (thường là biểu tượng menu hoặc mũi tên) nằm trênAppBarvà có nhiệm vụ đóng/mở lớp phía sau.backLayer: Widget được hiển thị khi lớp phía trước được kéo xuống. Ở đây, chúng ta có mộtColumnchứa cácElevatedButtonđể chọn màu.frontLayer: Widget hiển thị nội dung chính. Ở đây, là mộtContainercó màu nền thay đổi dựa trên lựa chọn từbackLayer.- Khi một nút màu được nhấn trong
backLayer, hàmsetStatesẽ cập nhật_selectedColorvà_selectedColorName. Điều quan trọng là sau đó chúng ta gọiBackdrop.of(context).revealBackLayer();(hoặcconcealBackLayer()nếu đang ở trạng thái reveal) để tự động đóng lớp phía sau và hiển thị lại lớp phía trước với màu mới.
3. Mẹo (Best Practices) để ghi nhớ và dùng thực tế
- Tính Contextual là Vàng: Luôn nhớ rằng các điều khiển ở
backLayerphải có liên quan trực tiếp đến nội dung ởfrontLayer. Đừng biến nó thành một cái Drawer thứ hai chứa đủ thứ linh tinh không liên quan. Ví dụ: NếufrontLayerhiển thị danh sách sản phẩm,backLayernên là bộ lọc hoặc tùy chọn sắp xếp. - Đơn Giản Hóa
backLayer:backLayernên là một bảng điều khiển gọn gàng, không phải một màn hình phức tạp. Tránh đặt quá nhiều widget hay logic phức tạp ở đây, vì nó có thể ảnh hưởng đến hiệu suất và trải nghiệm người dùng. - Affordance Rõ Ràng: Đảm bảo người dùng dễ dàng nhận ra cách đóng/mở Backdrop. Nút
BackdropToggleButtontrênAppBarlà một ví dụ tuyệt vời. - Quản Lý Trạng Thái (State Management): Đối với các ứng dụng lớn, việc thay đổi trạng thái từ
backLayerảnh hưởng đếnfrontLayernên được quản lý bằng các giải pháp như Provider, BLoC, Riverpod, hoặc GetX để code được sạch sẽ và dễ bảo trì hơn thay vì chỉ dùngsetStateđơn thuần. - Tối Ưu Hiệu Suất: Mặc dù
backLayerkhông hiển thị, các widget bên trong nó vẫn có thể được xây dựng. NếubackLayerquá nặng, hãy cân nhắc tối ưu hóa hoặc dùngVisibilitynếu cần để tránh xây dựng lại những phần không cần thiết.
4. Ứng dụng thực tế các Website/Ứng dụng đã dùng
Backdrop là một pattern khá phổ biến trong các ứng dụng di động, đặc biệt là những ứng dụng cần nhiều tùy chọn lọc hoặc cài đặt ngữ cảnh. Dù không phải lúc nào cũng sử dụng chính xác BackdropScaffold của Flutter, nhưng ý tưởng về hai lớp UI tương tác như vậy được áp dụng rộng rãi:
- Ứng dụng Chỉnh sửa Ảnh/Video: Rất nhiều ứng dụng chỉnh sửa ảnh/video sử dụng một biến thể của Backdrop. Lớp phía trước là ảnh/video bạn đang chỉnh sửa, và lớp phía sau (thường là một panel kéo lên từ dưới hoặc từ cạnh) chứa các công cụ, bộ lọc, thanh trượt điều chỉnh (độ sáng, tương phản...). Ví dụ: các ứng dụng như Snapseed (Google) có thể không dùng Backdrop y hệt, nhưng ý tưởng về việc ẩn/hiện các công cụ chỉnh sửa để tập trung vào hình ảnh là tương tự.
- Ứng dụng Thương mại điện tử: Khi bạn duyệt danh sách sản phẩm, thường có một nút 'Lọc' hoặc 'Sắp xếp'. Khi nhấn vào, một bảng điều khiển (có thể là bottom sheet hoặc một màn hình phủ) sẽ hiện ra với các tùy chọn lọc theo giá, màu sắc, kích thước... Đây là một hình thức tương tự Backdrop, nơi danh sách sản phẩm là
frontLayervà bộ lọc làbackLayer. - Ứng dụng Quản lý Tác vụ/Ghi chú: Một số ứng dụng có thể sử dụng Backdrop để hiển thị các tùy chọn sắp xếp, nhóm tác vụ, hoặc cài đặt hiển thị cho danh sách tác vụ chính.
Backdrop không chỉ là một widget, nó là một triết lý thiết kế giúp bạn tạo ra những giao diện ứng dụng gọn gàng, mạnh mẽ và thân thiện với người dùng. Hãy nhớ rằng, sân khấu của bạn càng được tổ chức tốt ở hậu trường, màn trình diễn ở phía trước càng trở nên ấn tượng!
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é!