Flutter 基礎(六)Material 元件之 BottomNavigationBar、TabBar、Drawer

NiZerin發表於2019-06-12

圖片

前言

在上一篇 Flutter基礎(五)Material元件最佳入門(前篇)中,我介紹了Material元件的MaterialApp、Scaffold、AppBar,這篇文章接著介紹Material元件中的BottomNavigationBar、TabBar、Drawer。

1.BottomNavigationBar

BottomNavigationBar是底部的導航欄,用於在3到5個的少量檢視中進行選擇。一般情況下,導航欄的選項卡由文字標籤、圖示或兩者結合的形式組成。
底部導航欄通常與javaScaffold結合使用,它會作為Scaffold.bottomNavigationBar引數。


import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
 static const String _title = 'Flutter Code Sample';

 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 home: MyStatefulWidget(),
 );
 }
}

class MyStatefulWidget extends StatefulWidget {
 MyStatefulWidget({Key key}) : super(key: key);

 @override
 _MyStatefulWidgetState createState() => _MyStatefulWidgetState();//1
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
 int _selectedIndex = 0;
 static const List<Widget> _widget = <Widget>[
 Text(
 'Index 0:首頁',
 ),
 Text(
 'Index 1: 通訊錄',
 ),
 Text(
 'Index 2: 設定',
 ),
 ];

 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('BottomNavigationBar示例'),
 ),
 body: Center(
 child: _widget.elementAt(_selectedIndex),
 ),
 bottomNavigationBar: BottomNavigationBar(
 items: const <BottomNavigationBarItem>[
 BottomNavigationBarItem(
 icon: Icon(Icons.home),
 title: Text('首頁'),
 ),
 BottomNavigationBarItem(
 icon: Icon(Icons.contacts),
 title: Text('通訊錄'),
 ),
 BottomNavigationBarItem(
 icon: Icon(Icons.build),
 title: Text('設定'),
 ),
 ],
 currentIndex: _selectedIndex,
 selectedItemColor: Colors.amber,
 onTap: _onItemTapped, //2
 ),
 );
 }
 void _onItemTapped(int index) {
 setState(() {
 _selectedIndex = index;
 });
 }
}

由於使用的Widget需要在Widget的生命週期中改變狀態,因此MyStatefulWidget繼承了StatefulWidget。註釋1處的createState方法會為此Widget建立可變狀態。註釋2處的onTap屬性會在點選其中一個選項卡時呼叫,它的值由_onItemTapped方法定義,在這個方法中設定當前的索引賦值給_selectedIndex,這樣通過_selectedIndex的值就可以切換選項卡了。實現的效果如下所示,可以通過點選選項卡來切換介面。
VYUinA.png

2.TabBar

TabBar用於顯示水平的選項卡,和Android中的TabLayout類似。TabBar通常需要配合TabBarView和TabController。其中TabBarView用於顯示與當前所選的選項卡對應的Widget檢視;TabController顧名思義就是TabBarView和TabBar的控制器,是這兩個Widget的橋樑。實現TabController有兩種方式,一種是用系統的DefaultTabController,另一種是自定義TabController。

2.1 使用DefaultTabController

DefaultTabController這種方式方便快捷,直接新建一個DefaultTabController就可以了。


import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 home: MyTabController(),
 );
 }
}
class MyTabController extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return DefaultTabController(
 length: 3,
 child: Scaffold(
 appBar: AppBar(
 title: Text('DefaultTabController示例'),
 bottom: TabBar(
 tabs: <Widget>[
 Tab(
 text: '熱點',
 ),
 Tab(
 text: '體育',
 ),
 Tab(
 text: '科技',
 ),
 ],
 ),
 ),
 body: TabBarView(
 children: <Widget>[
 Center(child: Text('熱點')),
 Center(child: Text('體育')),
 Center(child: Text('科技')),
 ],
 ),
 ),
 );
 }
}

2.2 自定義TabController

如果想要切換動畫或者監聽切換的互動,可以自定義TabController,需要實現SingleTickerProviderStateMixin。


import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 home: MyStatefulWidget(),
 );
 }
}

class MyStatefulWidget extends StatefulWidget {
 MyStatefulWidget({Key key}) : super(key: key);
 @override
 _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget>
 with SingleTickerProviderStateMixin {
 TabController _tabController;

 void initState() {
 super.initState();
 _tabController = TabController(vsync: this, length: 3);
 }

 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('自定義TabController'),
 bottom: TabBar(
 tabs: <Widget>[
 Tab(
 text: '熱點',
 ),
 Tab(
 text: '體育',
 ),
 Tab(
 text: '科技',
 ),
 ],
 controller: _tabController,//1
 ),
 ),
 body: TabBarView(
 controller: _tabController,
 children: <Widget>[
 Center(child: Text('熱點')),
 Center(child: Text('體育')),
 Center(child: Text('科技')),
 ],
 ),
 );
 }
 @override
 void dispose() {
 _tabController.dispose();
 super.dispose();
 }
}

和第一種使用DefaultTabController有兩點不同,一個是使用了StatefulWidget,另一個是在註釋1處將TabBar的controller設定為新建的TabController。執行效果如下所示,可以通過滑動介面和點選選項卡來切換介面。
VNYY3F.png

3.Drawer

Drawer就是抽屜,可以實現拉出推入的效果,和Android中的DrawerLayout類似。Drawer通常與Scaffold.drawer屬性一起使用,抽屜的子項通常是ListView,其第一個子項是頭部,頭部主要有兩個Widget可以實現:

  • DrawerHeader:展示基本的資訊
  • UserAccountsDrawerHeader:展示使用者頭像、使用者名稱、Email等資訊。

    import 'package:flutter/material.dart';

    void main() => runApp(MyApp());

    class MyApp extends StatelessWidget {
     static const String _title = 'Flutter Code Sample';

     @override
     Widget build(BuildContext context) {
     return MaterialApp(
     home: MyStatefulWidget(),
     );
     }
    }

    class MyStatefulWidget extends StatefulWidget {
     MyStatefulWidget({Key key}) : super(key: key);

     @override
     _DrawerState createState() => _DrawerState();
    }

    class _DrawerState extends State<MyStatefulWidget> {
     @override
     Widget build(BuildContext context) {
     return Scaffold(
     appBar: AppBar(
     title: Text('Drawer例子'),
     ),
     drawer: _drawer,
     );
     }
     get _drawer => Drawer(
     child: ListView(//1
     padding: EdgeInsets.zero,
     children: <Widget>[
     UserAccountsDrawerHeader(
     accountName: Text('劉望舒'),
     accountEmail: Text('liuwangshu.gmail.com'),
     currentAccountPicture: CircleAvatar(
     child: Text('X'),
     ),
     ),
     ListTile(
     leading: Icon(Icons.local_post_office),
     title: Text('郵件'),
     ),
     ListTile(
     leading: Icon(Icons.settings),
     title: Text('設定'),
     )
     ],
     ),
     );
    }

跟以往例子不同的是,由於drawer屬性的程式碼比較多,為了提高可讀性,我將drawer屬性的值抽取出來,通過getter的形式進行獲取。註釋1處可以看出Drawer的子項為ListView,ListView的通過ListTile來顯示每一個列表項。註釋2使用的是UserAccountsDrawerHeader,可以很輕鬆的設定使用者的姓名、郵箱、使用者圖片等。效果如下圖所示:
VU8Nss.png

總結

加上上一篇文章,我已經介紹了Material元件中應用程式結構和導航分類中的大部分Widget,另外Material元件所包含的其他的Widget,本系列就不介紹了,想要了解的可以檢視文件:https://flutter.dev/docs/development/ui/wi...


By: Laravel-China 寧澤林
MyBlog: nizer.in

相關文章