Flutter: Navigation và Routing cơ bản
· 4 min read
Navigation và Routing là những khái niệm quan trọng trong phát triển ứng dụng Flutter. Bài viết này sẽ hướng dẫn bạn cách thực hiện điều hướng giữa các màn hình và quản lý route trong ứng dụng Flutter.
1. Navigation cơ bản
1.1. Điều hướng đơn giản
// Điều hướng đến màn hình mới
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
// Quay lại màn hình trước
Navigator.pop(context);
1.2. Điều hướng với tham số
// Điều hướng và truyền tham số
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(item: item),
),
);
// Nhận tham số trong màn hình đích
class DetailScreen extends StatelessWidget {
final Item item;
const DetailScreen({Key? key, required this.item}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(item.title)),
body: Center(child: Text(item.description)),
);
}
}
2. Named Routes
2.1. Định nghĩa routes
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/details': (context) => DetailScreen(),
'/settings': (context) => SettingsScreen(),
},
);
2.2. Điều hướng với named routes
// Điều hướng đến route đã đặt tên
Navigator.pushNamed(context, '/details');
// Điều hướng và truyền tham số
Navigator.pushNamed(
context,
'/details',
arguments: item,
);
// Nhận tham số trong màn hình đích
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final item = ModalRoute.of(context)!.settings.arguments as Item;
return Scaffold(
appBar: AppBar(title: Text(item.title)),
body: Center(child: Text(item.description)),
);
}
}
3. Nested Navigation
3.1. Bottom Navigation Bar
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int _selectedIndex = 0;
final List<Widget> _screens = [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: _screens[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: (index) {
setState(() {
_selectedIndex = index;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
],
),
);
}
}
3.2. TabBar
class TabScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.home), text: 'Home'),
Tab(icon: Icon(Icons.search), text: 'Search'),
Tab(icon: Icon(Icons.person), text: 'Profile'),
],
),
),
body: TabBarView(
children: [
HomeScreen(),
SearchScreen(),
ProfileScreen(),
],
),
),
);
}
}
4. Best Practices
4.1. Quản lý Route
- Sử dụng named routes cho các màn hình chính
- Tổ chức routes theo cấu trúc rõ ràng
- Xử lý các trường hợp route không tồn tại
MaterialApp(
onUnknownRoute: (settings) {
return MaterialPageRoute(
builder: (context) => NotFoundScreen(),
);
},
);
4.2. Xử lý Back Button
WillPopScope(
onWillPop: () async {
// Xử lý khi người dùng nhấn nút back
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Thoát?'),
content: Text('Bạn có muốn thoát không?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: Text('Không'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: Text('Có'),
),
],
),
);
},
child: Scaffold(
// ...
),
);
4.3. Deep Linking
MaterialApp(
onGenerateRoute: (settings) {
// Xử lý deep link
if (settings.name?.startsWith('/product/') ?? false) {
final productId = settings.name!.split('/').last;
return MaterialPageRoute(
builder: (context) => ProductScreen(id: productId),
);
}
return null;
},
);
5. Ví dụ thực tế
5.1. Ứng dụng E-commerce
class EcommerceApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/categories': (context) => CategoriesScreen(),
'/product': (context) => ProductScreen(),
'/cart': (context) => CartScreen(),
'/checkout': (context) => CheckoutScreen(),
},
);
}
}
5.2. Ứng dụng Social Media
class SocialApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => FeedScreen(),
'/profile': (context) => ProfileScreen(),
'/messages': (context) => MessagesScreen(),
'/notifications': (context) => NotificationsScreen(),
},
);
}
}
Kết luận
Navigation và Routing là những khái niệm cơ bản nhưng quan trọng trong phát triển ứng dụng Flutter. Việc hiểu rõ và áp dụng đúng cách sẽ giúp bạn tạo ra trải nghiệm người dùng tốt hơn.
Tài liệu tham khảo: