1,建立單個導航圖標文字組件文件
import 'package:flutter/material.dart';
class NavigationIconView {
// 建立兩個屬性,一個是 用來展現 icon, 一個是動畫處理
final BottomNavigationBarItem item;
final AnimationController controller;
// 相似於 java 中的構造方法
// 建立 NavigationIconView 須要傳入三個參數, icon 圖標,title 標題, TickerProvider
NavigationIconView({Widget icon, Widget title, TickerProvider vsync})
: item = new BottomNavigationBarItem(
icon: icon,
title: title,
),
controller = new AnimationController(
duration: kThemeAnimationDuration, // 設置動畫持續的時間
vsync: vsync // 默認屬性和參數
);
}複製代碼
2,建立4個頁面home,course,book,my,如下只列出其中一個頁面代碼,其餘都同樣
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('首頁'),
actions: <Widget>[
new Container()
],
),
body: new Center(
child: null,
),
),
);
}
}
複製代碼
3,建立index頁面,用來渲染導航的佈局
import 'package:flutter/material.dart';
import 'package:flutter_app/home/home_page.dart';
import 'package:flutter_app/course/course_page.dart';
import 'package:flutter_app/book/book_page.dart';
import 'package:flutter_app/my/my_page.dart';
import 'package:flutter_app/navigation_icon_view.dart'; // 若是是在同一個包的路徑下,能夠直接使用對應的文件名
// 建立一個 帶有狀態的 Widget Index
class Index extends StatefulWidget {
// 固定的寫法
@override
State<StatefulWidget> createState() => new _IndexState();
}
// 要讓主頁面 Index 支持動效,要在它的定義中附加mixin類型的對象TickerProviderStateMixin
class _IndexState extends State<Index> with TickerProviderStateMixin {
int _currentIndex = 0; // 當前界面的索引值
List<NavigationIconView> _navigationViews; // 底部圖標按鈕區域
List<StatefulWidget> _pageList; // 用來存放咱們的圖標對應的頁面
StatefulWidget _currentPage; // 當前的顯示頁面
// 定義一個空的設置狀態值的方法
void _rebuild() {
setState(() {});
}
@override
void initState() {
super.initState();
// 初始化導航圖標
_navigationViews = <NavigationIconView>[
new NavigationIconView(
icon: new Icon(Icons.home), title: new Text("首頁"), vsync: this),
// vsync 默認屬性和參數
new NavigationIconView(
icon: new Icon(Icons.videocam),
title: new Text("課程"),
vsync: this),
new NavigationIconView(
icon: new Icon(Icons.book), title: new Text("書籍"), vsync: this),
new NavigationIconView(
icon: new Icon(Icons.perm_identity),
title: new Text("個人"),
vsync: this),
];
// 給每個按鈕區域加上監聽
for (NavigationIconView view in _navigationViews) {
view.controller.addListener(_rebuild);
}
// 將咱們 bottomBar 上面的按鈕圖標對應的頁面存放起來,方便咱們在點擊的時候
_pageList = <StatefulWidget>[
HomePage(),
CoursePage(),
BookPage(),
MyPage()
];
_currentPage = _pageList[_currentIndex];
}
@override
Widget build(BuildContext context) {
// 聲明定義一個 底部導航的工具欄
final BottomNavigationBar bottomNavigationBar = new BottomNavigationBar(
items: _navigationViews
.map((NavigationIconView navigationIconView) =>
navigationIconView.item)
.toList(), // 添加 icon 按鈕
currentIndex: _currentIndex, // 當前點擊的索引值
type: BottomNavigationBarType.fixed, // 設置底部導航工具欄的類型:fixed 固定
onTap: (int index) {
// 添加點擊事件
setState(() {
// 點擊以後,須要觸發的邏輯事件
_navigationViews[_currentIndex].controller.reverse();
_currentIndex = index;
_navigationViews[_currentIndex].controller.forward();
_currentPage = _pageList[_currentIndex];
});
},
);
return new MaterialApp(
home: new Scaffold(
body: new Center(child: _currentPage // 動態的展現咱們當前的頁面
),
bottomNavigationBar: bottomNavigationBar, // 底部工具欄
),
theme: new ThemeData(
primarySwatch: Colors.blue, // 設置主題顏色
),
);
}
}
複製代碼
4,main.dart代碼以下
import 'package:flutter/material.dart';
import 'package:flutter_app/index/Index.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Colors.red,
),
home: Index(),
);
}
}
複製代碼
5,測試運行
![](http://static.javashuo.com/static/loading.gif)