Nguồn : [Navigation and routing | Flutter](https://docs.flutter.dev/ui/navigation) |
I. TỔNG QUAN
- Navigator hỗ trợ
Push
vàPop
Route
onPressed: () { Navigator.of(context).push( //Nếu style của app là Material //Sử dụng MaterialPageRoute là tham số cho hàm push. MaterialPageRoute( builder: (context) => const SongScreen(song: song), ), ); },
- Nếu bạn không muốn dùng
Screen
, bạn có thể config name để routing.
@override Widget build(BuildContext context) { return MaterialApp( routes: { '/': (context) => HomeScreen(), '/details': (context) => DetailScreen(), }, ); }
- NOTE : Theo document Flutter, k nên dùng nó vì khi sử dụng deeplink nó luôn Push một Route mới mà k quan tâm app bạn đang hiển thị route nào.
- Dùng Router
- Ưu điểm của nó là khi deeplink , nó k tạo ra route mới route đó đã có.
- Để dùng nó, MaterialApp có tạo săn contructors là
router
, với tham số làrouterConfig
MaterialApp.router( routerConfig: GoRouter( // … ) );
- NOTE : GoRouter là một gói hỗ trợ routing, nếu bạn k thích dùng nó mà muốn tự custom vẫn được. Orverride lại 2 hàm này
RouteInformationParser
vàRouterDelegate
- Router và Navigator nó thiết kế để tương thích với nhau, nên hàm
push
vàpop
vẫn dùng được.
II. Làm Việc Với Tabs
- Dùng widget
DefaultTabController
length
: Xác định số lượng tabchild
: Nên là một Scaffold widget.
- Tabbar : Dùng để khai báo các item Tab.
- TabbarView : Dùng để khai báo content của Tab.
import 'package:flutter/material.dart'; void main() { runApp(const TabBarDemo()); } class TabBarDemo extends StatelessWidget { const TabBarDemo({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: DefaultTabController( length: 3, // Số Lượng Tab child: Scaffold( appBar: AppBar( bottom: const TabBar( tabs: [ Tab(icon: Icon(Icons.directions_car)), Tab(icon: Icon(Icons.directions_transit)), Tab(icon: Icon(Icons.directions_bike)), ], ), title: const Text('Tabs Demo'), ), body: const TabBarView( children: [ Icon(Icons.directions_car), Icon(Icons.directions_transit), Icon(Icons.directions_bike), ], ), ), ), ); } }
III. Navigate Đến Màn Hình Mới Và Trở Lại.
- Dùng hàm
push
vàpop
// Within the `FirstRoute` widget onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => const SecondRoute()), ); }
// Within the SecondRoute widget onPressed: () { Navigator.pop(context); }
IV. GỬI VÀ NHẬN DATA
- Gửi Data :
- Cách 1 : Truyền qua contructors, Cách này dùng chán, mỗi lần truyền phải contructor để nhận data, tự tham khảm document.
-
Cách 2 : Dùng thông qua Arguments
MaterialPageRoute( builder: (context) => const DetailScreen(), // Pass the arguments as part of the RouteSettings. The // DetailScreen reads the arguments from these settings. settings: RouteSettings( //Truyền data tại đây. Data là một Object muốn truyền gì cũng được :v arguments: todos[index], ),
- Màn hình mới thì lấy nó ra như thế này :
//Phải ép kiểu về, agruments cho chỉ biết mỗi Object. final todo = ModalRoute.of(context)!.settings.arguments as Todo;
- Nhận Data
-
Hàm
pop
của Navigator nó hỗ trợ, cứ truyền data muốn trả về thôiNavigator.pop(context, data);
-
Muốn nhận data trả được trả về thì lúc bạn push phải đợi. Cụ thể là phải await nó =))
//Thằng result chính là data từ màn hình vừa trả về final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => const SelectionScreen()), );
-
IV. Drawer
- Nó là cái hamburger menu đấy.
- Để thực hiện thì làm theo các bước
- Khai báo widget Scaffold
- Setting widget Drawer vào thuộc tính
drawer
của Scaffold - Layout Drawer thông qua thuộc tính
child
Navigator.pop(context)
để đóng drawer.
-
Đoạn code dưới đây mình chỉ mổ ta phần chính của Drawer, muốn xem full thì vào đây
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.title)), body: Center( child: _widgetOptions[_selectedIndex], ), // Widget Drawer drawer: Drawer( // Child nó yêu cầu widget, nên bạn dùng widget nào cùng được // Nhưng để hợp lí thì mình dùng ListView để hiển thị các item child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: [ //Nó có widget DrawerHeader để làm header cho drawer const DrawerHeader( decoration: BoxDecoration( color: Colors.blue, ), child: Text('Drawer Header'), ), ListTile( title: const Text('Home'), selected: _selectedIndex == 0, onTap: () { // Update the state of the app _onItemTapped(0); //Muốn đóng drawer thì dùng hàm pop thôi Navigator.pop(context); }, ), ListTile( title: const Text('Business'), selected: _selectedIndex == 1, onTap: () { // Update the state of the app _onItemTapped(1); //Muốn đóng drawer thì dùng hàm pop thôi Navigator.pop(context); }, ), ListTile( title: const Text('School'), selected: _selectedIndex == 2, onTap: () { // Update the state of the app _onItemTapped(2); //Muốn đóng drawer thì dùng hàm pop thôi Navigator.pop(context); }, ), ], ), ), ); }
V. Cài Đặt Deeplink
- Phần này nói sau, đang study chưa cần ưu tiên.