
Chào các lập trình viên tương lai, hoặc những người đã "lăn lộn" với code đủ để hiểu rằng UI/UX không chỉ là màu mè mà là linh hồn của ứng dụng! Tôi là Creyt, và hôm nay chúng ta sẽ mổ xẻ một "phù thủy" trong thế giới Flutter: FlexibleSpaceBar.
1. FlexibleSpaceBar là gì và tại sao chúng ta cần nó?
Hãy hình dung thế này: Bạn có một chiếc xe thể thao siêu ngầu, nhưng đôi khi bạn muốn nó biến hình thành một chiếc SUV đa dụng để chở đồ, rồi lại thu gọn thành xe đua khi cần tốc độ. Trong thế giới Flutter, FlexibleSpaceBar chính là cái "bộ phận biến hình" đó cho AppBar của bạn.
Nói một cách hàn lâm hơn, FlexibleSpaceBar là một widget được thiết kế để hoạt động bên trong SliverAppBar. Nhiệm vụ chính của nó là tạo ra một vùng không gian linh hoạt ở phần đầu ứng dụng, cho phép AppBar của bạn co giãn một cách mượt mà khi người dùng cuộn (scroll). Khi bạn cuộn xuống, FlexibleSpaceBar có thể mở rộng ra, tiết lộ thêm nội dung như một hình ảnh nền lớn, một tiêu đề ấn tượng, hoặc bất kỳ widget nào bạn muốn. Ngược lại, khi bạn cuộn lên, nó sẽ thu gọn lại, để lại một AppBar nhỏ gọn, tinh tế.
Tại sao chúng ta cần nó ư? Đơn giản thôi. Trong thời đại mà người dùng đòi hỏi trải nghiệm mượt mà, trực quan, thì một AppBar tĩnh như "tượng đài" là không đủ. FlexibleSpaceBar giúp ứng dụng của bạn trở nên sống động, tương tác hơn, tạo hiệu ứng parallax (hiệu ứng thị sai) cực kỳ hút mắt, khiến người dùng cảm thấy như đang lướt trên một trang web cao cấp chứ không phải một ứng dụng di động thông thường. Nó là chìa khóa để biến những giao diện "đơn thuần" thành "đẳng cấp".

2. Code Ví Dụ Minh Họa: Biến hình cùng FlexibleSpaceBar
Để FlexibleSpaceBar phát huy sức mạnh, chúng ta cần đặt nó vào đúng "khung sườn" của nó, đó chính là SliverAppBar, và tất cả sẽ nằm trong một CustomScrollView. Nghe có vẻ phức tạp, nhưng hãy xem ví dụ này, nó đơn giản hơn bạn nghĩ nhiều:
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: 'FlexibleSpaceBar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
appBarTheme: const AppBarTheme(
backgroundColor: Colors.deepPurple, // Màu nền mặc định cho AppBar
),
),
home: const FlexibleSpaceBarExample(),
);
}
}
class FlexibleSpaceBarExample extends StatelessWidget {
const FlexibleSpaceBarExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 250.0, // Chiều cao tối đa khi App Bar mở rộng
floating: false, // Không trôi nổi khi cuộn xuống một chút
pinned: true, // Luôn ghim App Bar ở trên cùng khi thu gọn
flexibleSpace: FlexibleSpaceBar(
centerTitle: true, // Căn giữa tiêu đề khi App Bar thu gọn
title: const Text(
'Lớp Học Flutter Của Thầy Creyt',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
background: Image.network(
'https://picsum.photos/id/1043/800/400', // Hình nền sẽ co giãn và tạo hiệu ứng parallax
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
},
errorBuilder: (context, error, stackTrace) =>
const Center(child: Icon(Icons.error)),
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: index.isOdd ? Colors.white : Colors.grey[100],
height: 120.0,
child: Center(
child: Text(
'Bài học số ${index + 1}: Khái niệm Flutter nâng cao',
style: const TextStyle(fontSize: 18, color: Colors.black87),
),
),
);
},
childCount: 25, // Tạo 25 mục để có thể cuộn
),
),
],
),
);
}
}
Trong ví dụ trên:
CustomScrollView: Là "con đường" chứa tất cả cácSliver(các phần có thể cuộn được).SliverAppBar: Là "chiếc xe" của chúng ta.expandedHeight: Xác định chiều cao tối đa củaAppBarkhi nó được mở rộng hoàn toàn. Hãy coi nó là "chiều cao khi xe biến hình thành SUV".pinned: true: Đảm bảo rằng khi bạn cuộn lên,AppBarsẽ thu gọn lại và "ghim" ở đầu màn hình, không biến mất hoàn toàn.flexibleSpace: FlexibleSpaceBar(...): Đây chính là "bộ phận biến hình" mà chúng ta đang nói đến.title: Widget này (thường làText) sẽ xuất hiện khiAppBarthu gọn và sẽ di chuyển, mờ dần/hiện ra khiAppBarco giãn.background: Đây là nơi bạn đặt hình ảnh hoặc bất kỳ widget nào mà bạn muốn nó xuất hiện ở phần nền củaAppBarkhi nó mở rộng. Nó sẽ tự động tạo hiệu ứng parallax khi cuộn.centerTitle: true: KhiAppBarthu gọn, tiêu đề sẽ được căn giữa.
3. Mẹo Vặt & Best Practices Từ Lão Làng Creyt
Để dùng FlexibleSpaceBar một cách "thượng thừa", đây là vài mẹo nhỏ mà tôi đã đúc kết được sau bao năm "xông pha trận mạc":
- Hiệu ứng Parallax đỉnh cao: Hãy luôn đặt một
Image.networkhoặcImage.assetvào thuộc tínhbackgroundcủaFlexibleSpaceBar. Flutter sẽ tự động xử lý hiệu ứng parallax (hình nền di chuyển chậm hơn nội dung) một cách mượt mà, tạo cảm giác chiều sâu rất ấn tượng. - Kết hợp
SliverAppBar:pinned: true: Gần như luôn luôn nên dùngtrue. Nó giữ choAppBarthu gọn ở trên cùng, mang lại trải nghiệm người dùng quen thuộc và tiện lợi.floating: truevàsnap: true: Nếu bạn muốnAppBartự động hiện lại ngay lập tức khi người dùng cuộn xuống một chút (thay vì phải cuộn hết lên đầu), hãy dùngfloating: true. Kết hợp vớisnap: true, nó sẽ tự động "bật" ra hoặc "thu" lại hoàn toàn thay vì dừng ở lưng chừng.expandedHeight: Đừng quá ham hố chiều cao lớn. Hãy chọn một giá trị vừa phải (ví dụ: 150-250px) để không chiếm quá nhiều không gian màn hình trên các thiết bị nhỏ.
- Nội dung
title: Tiêu đề trongFlexibleSpaceBarsẽ tự động thay đổi kích thước và vị trí. Hãy giữ nó ngắn gọn, súc tích để dễ đọc khiAppBarthu gọn. Nếu cần nhiều thông tin hơn, hãy cân nhắc dùng mộtStacktrongbackgroundđể chồng các widget lên nhau. - Tránh "nhồi nhét": Mặc dù bạn có thể đặt bất kỳ widget nào vào
background, đừng nhồi nhét quá nhiều logic phức tạp hoặc widget nặng nề vào đó. Mục đích chính là tạo hiệu ứng thị giác, không phải là nơi chứa đựng toàn bộ giao diện.
4. Ứng Dụng Thực Tế: Ai đang dùng "phép thuật" này?
Bạn có thể không nhận ra, nhưng hiệu ứng của FlexibleSpaceBar đã và đang được rất nhiều ứng dụng lớn sử dụng để nâng tầm trải nghiệm người dùng:
- Ứng dụng Mạng xã hội: Hãy mở profile của bạn trên LinkedIn, Facebook, hoặc Instagram. Bạn sẽ thấy hình ảnh bìa (cover photo) thường chiếm một diện tích lớn ở trên cùng, và khi bạn cuộn xuống xem các bài đăng, hình ảnh đó sẽ thu nhỏ dần, hoặc biến mất, để lại một thanh tiêu đề nhỏ gọn. Đó chính là hiệu ứng tương tự mà
FlexibleSpaceBarmang lại. - Ứng dụng Đọc tin tức/Blog: Khi bạn đọc một bài báo trên các ứng dụng như Google News hay các trang blog lớn, phần tiêu đề hoặc hình ảnh đại diện của bài viết thường rất lớn ở đầu trang, sau đó co lại khi bạn cuộn xuống nội dung.
- Trang sản phẩm E-commerce: Các ứng dụng mua sắm như Shopee, Lazada (hoặc các phiên bản quốc tế như Amazon) thường có trang chi tiết sản phẩm với một carousel hình ảnh lớn ở trên cùng. Khi cuộn, phần này cũng sẽ thu gọn lại.
- Ứng dụng Âm nhạc/Video: Các trang thông tin về album, nghệ sĩ trên Spotify, YouTube Music hay trang kênh trên YouTube cũng thường dùng hiệu ứng này để hiển thị ảnh bìa album/kênh và thông tin, sau đó thu gọn khi người dùng cuộn qua danh sách bài hát/video.
Tóm lại, FlexibleSpaceBar không chỉ là một widget đẹp mắt, mà còn là một công cụ mạnh mẽ để tạo ra các giao diện động, tương tác và chuyên nghiệp trong ứng dụng Flutter của bạn. Hãy thử nghiệm và sáng tạo với nó nhé!
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é!