# Navigation router ## ButtomTabs 底部的切換頁 ![](https://i.imgur.com/0usXoEW.png =40%x) 會使用到的內建widget: 1. BottomNavigationBar 2. BottomNavigationBarItem #### main.dart ```java import 'src/widgets/ButtomTabs.dart'; class App extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: GlobalLayout(title: 'flutter_router_demo'), ); } } void main() => runApp(App()); ``` ```java class GlobalLayout extends StatefulWidget { @override GlobalLayoutState createState() => GlobalLayoutState(); } class GlobalLayoutState extends State<GlobalLayout> { int current = 0; void onChangeTab(int n) { setState(() { current = n; }); } return Scaffold( //... bottomNavigationBar: ButtomTabs( current: current, onChangeTab: onChangeTab, ) ) } ``` #### ButtomTabs.dart ```java import 'package:flutter/material.dart'; class ButtomTabs extends StatelessWidget { ButtomTabs({this.current, this.onChangeTab}); final int current; final Function onChangeTab; @override Widget build(BuildContext context) { return BottomNavigationBar( type: BottomNavigationBarType.fixed, //超過3個item要強制設定fixed currentIndex: current, items: [ BottomNavigationBarItem(title: Text("Home"), icon: Icon(Icons.home)), BottomNavigationBarItem(title: Text("List"), icon: Icon(Icons.list)), BottomNavigationBarItem( title: Text("Message"), icon: Icon(Icons.message)), ], onTap: onChangeTab); } } ``` 當`BottomNavigationBarItem`數量超過3個的時候,`BottomNavigationBar`的`type`會從預設的`fixed`變成`shifting`,所以假設要放到4個或5個,要手動指定`type:BottomNavigationBarType.fixed`。 --- ## Drawer 左邊打開的漢堡選單 ![](https://i.imgur.com/x52UmOG.png =40%x) ![](https://i.imgur.com/BaWN0VG.png =40%x) #### main.dart ```java return Scaffold( drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: <Widget>[ DrawerHeader( decoration: BoxDecoration( color: Colors.red, ), child: Text( 'Drawer Header', style: TextStyle( color: Colors.white, fontSize: 24, ), ), ), ListTile( leading: Icon(Icons.message), title: Text('Messages'), ), ListTile(leading: Icon(Icons.access_alarms), title: Text('Alert')), ListTile(leading: Icon(Icons.device_hub), title: Text('Device')), ], )) ) ``` ### 使用`Listview.build()` #### main.dart ```java return Scaffold( drawer: DrawerItems(), ) ``` #### DrawerItems.dart ```java import 'package:flutter/material.dart'; class DrawerItems extends StatelessWidget { final List<Map<String, dynamic>> menus = [ {'name': 'Home', 'icon': 59530}, {'name': 'Account', 'icon': 59705}, {'name': 'Setting', 'icon': 59576}, ]; @override Widget build(BuildContext context) { return Drawer( child: ListView.builder( padding: EdgeInsets.zero, itemCount: menus.length + 1, itemBuilder: (BuildContext context, int i) { if (i == 0) { return DrawerHeader( decoration: BoxDecoration( color: Colors.red, ), child: Text( 'Drawer Header', style: TextStyle( color: Colors.white, fontSize: 24, ), ), ); } return ListTile( leading: Icon(IconData(menus[i - 1]["icon"], fontFamily: 'MaterialIcons')), title: Text(menus[i - 1]["name"]), ); })); } } ``` - `Drawer`:會從左邊打開一個固定寬度的區域,如果不加上這個,左側選單會變成滿版的。 - `itemCount`:因為最上面要新增一個`DrawerHeader`,所以`itemCount`要+1。 - `return`:`(i == 0)`的時候return `DrawerHeader`,其他時候return 一般的`ListTile`。 ### 加入點擊事件 #### main.dart 加入`router` ```java import 'src/pages/PageWrap.dart'; return MaterialApp( routes: <String, WidgetBuilder>{ '/account': (BuildContext context) => PageWrap(title: 'Account'), '/setting': (BuildContext context) => PageWrap(title: 'Setting'), }, ) ``` #### DrawerItems.dart - 選單的資料中,加入`path`資料。 ```java final List<Map<String, dynamic>> menus = [ {'name': 'Home', 'icon': 59530}, {'name': 'Account', 'path': 'account', 'icon': 59705}, {'name': 'Setting', 'path': 'setting', 'icon': 59576}, ]; ``` - `pushNamed`裡面是要放`/path/name`這種資料,所以字串前面加上一個`/` ```java return ListTile( //... onTap: () { Navigator.of(context).pushNamed('/${menus[i - 1]["path"]}'); }, ); ``` #### PageWrap.dart ```java import 'package:flutter/material.dart'; class PageWrap extends StatelessWidget { PageWrap({this.title}); final String title; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(title), ), body: Center( child: Text(title), ), ); } } ```