
Chào các lập trình viên tương lai, hoặc những 'phù thủy code' đang tìm cách biến UI của mình thành những màn trình diễn nghệ thuật! Anh Creyt đây, và hôm nay chúng ta sẽ mổ xẻ một công cụ cực kỳ xịn xò trong Flutter: HeroFlightShuttleBuilder.
1. HeroFlightShuttleBuilder là gì và để làm gì? (Kịch bản Hollywood của UI)
Các em hình dung thế này: Trong thế giới ứng dụng, đôi khi chúng ta muốn một vật thể (như tấm ảnh, avatar, hay một biểu tượng) bay mượt mà từ màn hình này sang màn hình khác khi người dùng tương tác. Nó giống như một cảnh trong phim Hollywood vậy, diễn viên chính (cái widget của mình) không biến mất rồi xuất hiện lại, mà là di chuyển một cách duyên dáng, tạo cảm giác liên tục, liền mạch. Đó chính là lúc Hero widget ra tay.
Hero widget trong Flutter sinh ra để làm điều đó. Nó là một cặp đôi hoàn hảo, một Hero ở màn hình nguồn và một Hero khác ở màn hình đích, cả hai cùng mang một tag chung. Khi các em chuyển màn hình, Flutter sẽ tự động tạo một hiệu ứng 'bay' cho widget con của Hero từ vị trí cũ sang vị trí mới. Mặc định, nó làm khá tốt rồi.
Nhưng đợi đã, nếu chúng ta muốn cái 'vật thể bay' đó không chỉ đơn thuần là bản sao của widget ban đầu? Nếu chúng ta muốn nó biến hình một chút trong lúc bay? Ví dụ, nó có thể mờ đi, xoay một vòng, hoặc thậm chí là đổi màu, đổi hình dạng một chút? Đây chính là lúc HeroFlightShuttleBuilder bước ra sân khấu, như một đạo diễn hiệu ứng đặc biệt vậy!
HeroFlightShuttleBuilder là một callback function mà các em có thể cung cấp cho widget Hero. Nó cho phép các em tùy chỉnh hoàn toàn widget sẽ được dùng để bay trong suốt quá trình chuyển tiếp. Thay vì để Flutter dùng widget mặc định, các em có thể tự tay tạo ra một 'tàu con thoi' riêng, độc đáo cho chuyến bay của mình. Nó giống như việc các em tự thiết kế chiếc máy bay riêng cho diễn viên chính thay vì dùng máy bay thương mại vậy. Quyền năng nằm trong tay các em!

2. Code Ví Dụ Minh Họa: 'Tàu Con Thoi' Biến Hình
Để minh họa, chúng ta sẽ tạo hai màn hình đơn giản. Một màn hình có một hình tròn nhỏ, và khi nhấn vào, nó sẽ bay sang màn hình thứ hai và biến thành một hình vuông với viền khác. Đây là lúc HeroFlightShuttleBuilder tỏa sáng.
Chúng ta sẽ tạo hai file:
main.dart (Để khởi chạy ứng dụng và định tuyến)
import 'package:flutter/material.dart';
import 'screen_one.dart';
import 'screen_two.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'HeroFlightShuttleBuilder Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ScreenOne(),
routes: {
'/screenTwo': (context) => const ScreenTwo(),
},
);
}
}
screen_one.dart (Màn hình nguồn với Hero widget và flightShuttleBuilder)
import 'package:flutter/material.dart';
class ScreenOne extends StatelessWidget {
const ScreenOne({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Màn hình 1 - Nguồn')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Hero(
tag: 'avatarHero',
// Đây là nơi chúng ta tùy chỉnh 'tàu con thoi' bay
flightShuttleBuilder: (BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext) {
// Trong quá trình bay, chúng ta muốn widget này xuất hiện
// Nó sẽ chuyển đổi từ hình tròn sang hình vuông với viền
return AnimatedBuilder(
animation: animation,
builder: (context, child) {
// animation.value sẽ từ 0.0 đến 1.0 trong suốt quá trình bay
// Chúng ta có thể dùng nó để điều khiển các hiệu ứng biến hình
final bool isReturning = flightDirection == HeroFlightDirection.pop;
final double progress = isReturning ? 1.0 - animation.value : animation.value;
return Container(
width: 100 + (progress * 50), // Tăng kích thước dần
height: 100 + (progress * 50),
decoration: BoxDecoration(
color: Color.lerp(Colors.red, Colors.blue, progress), // Đổi màu dần
borderRadius: BorderRadius.circular(50 * (1 - progress)), // Chuyển từ tròn sang vuông
border: Border.all(
color: Color.lerp(Colors.transparent, Colors.green, progress)!, // Thêm viền dần
width: 5 * progress,
),
),
child: const Center(
child: Text(
'Bay!',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
);
},
);
},
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/screenTwo');
},
child: Container(
width: 100,
height: 100,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: const Center(
child: Text(
'Nhấn tôi!',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
),
),
),
const SizedBox(height: 20),
const Text('Nhấn vào hình tròn để xem hiệu ứng bay đặc biệt!')
],
),
),
);
}
}
screen_two.dart (Màn hình đích với Hero widget)
import 'package:flutter/material.dart';
class ScreenTwo extends StatelessWidget {
const ScreenTwo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Màn hình 2 - Đích')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Hero(
tag: 'avatarHero',
child: Container(
width: 150,
height: 150,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(0), // Hình vuông
border: Border.all(color: Colors.green, width: 5),
),
child: const Center(
child: Text(
'Đã đến!',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
),
const SizedBox(height: 20),
const Text('Đây là đích đến của chuyến bay đặc biệt!')
],
),
),
);
}
}
Trong ví dụ trên, khi các em nhấn vào hình tròn màu đỏ ở ScreenOne, thay vì nó chỉ bay thẳng sang ScreenTwo và xuất hiện thành hình vuông màu xanh, thì trong quá trình bay, flightShuttleBuilder đã tạo ra một widget Container tùy chỉnh. Widget này sử dụng AnimatedBuilder và giá trị animation.value để thay đổi kích thước, màu sắc, bo góc và thêm viền một cách mượt mà, tạo hiệu ứng 'biến hình' cực kỳ thú vị. progress được tính toán để đảm bảo hiệu ứng đảo ngược khi quay lại màn hình trước.
3. Mẹo Vặt (Best Practices) khi dùng HeroFlightShuttleBuilder
- Chỉ dùng khi cần thiết: Đừng lạm dụng nó. Nếu hiệu ứng mặc định của
Herođã đủ tốt và phù hợp với thiết kế, hãy cứ để nó yên.HeroFlightShuttleBuildergiống như gia vị đặc biệt, chỉ nên dùng khi muốn tạo điểm nhấn độc đáo. - Giữ cho 'tàu con thoi' nhẹ nhàng: Widget mà
HeroFlightShuttleBuildertrả về chỉ tồn tại trong thời gian ngắn của hiệu ứng. Đừng nhét quá nhiều logic phức tạp hay widget nặng nề vào đó. Nó cần phải bay nhanh và mượt mà. - Đồng bộ hóa với
animation.value: Tham sốanimationlà chìa khóa. Nó cung cấp cho các em một giá trị từ 0.0 đến 1.0 trong suốt quá trình hiệu ứng. Hãy dùng nó để điều khiển các thuộc tính của widget (màu sắc, kích thước, độ mờ, transform...) để tạo ra hiệu ứng chuyển tiếp mượt mà và có mục đích. - Kiểm tra hướng bay (
flightDirection): Đôi khi, các em muốn hiệu ứng khác nhau khi bay đi (HeroFlightDirection.push) và bay về (HeroFlightDirection.pop). Tham sốflightDirectiongiúp các em phân biệt điều này để tùy chỉnh hành vi cho phù hợp. - Cân nhắc hiệu năng: Mặc dù Flutter rất tối ưu cho animation, nhưng nếu 'tàu con thoi' của các em quá phức tạp với nhiều hiệu ứng chồng chéo, hãy kiểm tra hiệu năng trên các thiết bị thực tế, đặc biệt là các thiết bị cấu hình thấp.
4. Ứng Dụng Thực Tế (Nơi các 'tàu con thoi' bay lượn)
HeroFlightShuttleBuilder nói riêng và Hero animation nói chung được sử dụng rộng rãi trong các ứng dụng để cải thiện trải nghiệm người dùng, tạo cảm giác chuyên nghiệp và liền mạch:
- Thư viện ảnh/Ứng dụng xem ảnh: Khi các em nhấn vào một hình thu nhỏ (thumbnail) trong danh sách, tấm ảnh đó sẽ bay và phóng to thành ảnh đầy đủ trên màn hình chi tiết. Đây là một ví dụ kinh điển của
Heroanimation. - Ứng dụng thương mại điện tử: Khi nhấn vào một sản phẩm trong danh sách (có thể là ảnh sản phẩm), ảnh đó sẽ bay đến màn hình chi tiết sản phẩm, tạo cảm giác sản phẩm 'nhảy' ra khỏi danh sách để người dùng xem kỹ hơn.
- Mạng xã hội/Ứng dụng hồ sơ cá nhân: Avatar của người dùng có thể bay từ danh sách bạn bè hoặc bài đăng lên màn hình hồ sơ cá nhân khi được nhấn vào.
- Bất kỳ ứng dụng nào có danh sách và chi tiết: Bất cứ khi nào có một phần tử trên danh sách mà khi nhấn vào, nó sẽ dẫn đến một màn hình chi tiết về chính phần tử đó,
Heroanimation là một lựa chọn tuyệt vời để tạo sự liên kết trực quan.
Tóm lại, HeroFlightShuttleBuilder là công cụ mạnh mẽ dành cho những ai muốn 'đạo diễn' các cảnh quay chuyển tiếp UI trong Flutter một cách tinh tế và độc đáo. Hãy dùng nó một cách khôn ngoan để biến ứng dụng của các em thành một tác phẩm nghệ thuật chuyển độ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é!