前言
Tabbar結(jié)構(gòu)的APP非常的常見,通常我們在iOS開發(fā)中,構(gòu)建這類結(jié)構(gòu)的頁面會涉及到UITabbarController,UINavigationController,UIViewController等組合來實(shí)現(xiàn),當(dāng)然了我們也可以通過自定義Tabbar來達(dá)到頁面效果。今天就給大家介紹一下在flutter中,實(shí)現(xiàn)Tabbar結(jié)構(gòu)的方式。先看下效果圖:

Scaffold
在我的理解中Scaffold是類似于ViewController的部件,而且它把在iOS中UITabbarController和UINavigationController通過屬性的方式都融合在了一起。比如我們給一個(gè)Scaffold設(shè)置了AppBar(UINavigationBar),它就類似于iOS下的UINavigationController的特征;當(dāng)設(shè)置了bottomNavigationBar(UITabbar)屬性,就具備了UITabbarController的特性;還有一個(gè)就是body屬性,非常類似于我們ViewController.view。
(在flutter下,UI布局的組合非常靈活,而且實(shí)現(xiàn)起來也非常的簡單)。
頁面目錄結(jié)構(gòu)

root_page里面可以理解為那個(gè) tabbarControllerpages 是tabar 指向的具體頁面,或者說是viewControllers
我們還是從main.dart開始
直接上代碼了,沒太多的解釋,需要解釋的地方,我會在代碼里面標(biāo)注。
import 'package:flutter/material.dart';
import 'package:flutterappzeze/root_page/root_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: RootPage(),
);
}
}
關(guān)于main.dart我在做開始的文章中就有介紹(main.dart),這里其實(shí)就做了一件事,就是將home(rootViewController)設(shè)置為RootPage()(root_page.dart)。
看下root_page.dart
import 'package:flutter/material.dart';
import 'package:flutterappzeze/pages/exam_page.dart';
import 'package:flutterappzeze/pages/pend_course.dart';
import 'package:flutterappzeze/pages/personal_page.dart';
import 'package:flutterappzeze/pages/taken_course.dart';
class RootPage extends StatefulWidget {
@override
_RootPageState createState() => _RootPageState();
}
class _RootPageState extends State<RootPage> {
int _currentIndex = 0; //當(dāng)前索引
// ViewControllers 自定義的widget對象
List <Widget> _viewControllers = [
PendCourse(), //待上課程
TakenCourse(), //已上課程
ExamPage(), //水平測試
PersonalPage(), //我
];
// tabBarItems 看變量的命名tabbarItems,應(yīng)該就知道是什么了
List <BottomNavigationBarItem> _tabBarItems = [
BottomNavigationBarItem(
icon: Icon(Icons.access_alarm), //上圖
title: Text('待上課程') //下文
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
title: Text('已上課程')
),
BottomNavigationBarItem(
icon: Icon(Icons.perm_camera_mic),
title: Text('水平測試')
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text('我')
),
];
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
bottomNavigationBar: BottomNavigationBar( //ios 的 tabbar
onTap: (int index){ //tabbar點(diǎn)擊回調(diào),返回當(dāng)前點(diǎn)擊的索引
_currentIndex = index;
setState(() {});
},
type:BottomNavigationBarType.fixed, //tabbar點(diǎn)擊風(fēng)格
fixedColor: Colors.green, //被點(diǎn)擊后的顏色
currentIndex: _currentIndex, //當(dāng)前點(diǎn)擊的是哪個(gè)
items: _tabBarItems, //類似于ios的TabbarItem,這里需要一個(gè)[List]
//*畢竟item是有多個(gè),只不過這里的item 類型是BottomNavigationBarItem
//*ios下其實(shí)就是我們的UITabbarItem
),
body: _viewControllers[_currentIndex], //viewControllers,
//*當(dāng)觸發(fā)onTap,根據(jù)_currentIndex 來動態(tài)切換,我把他們放在了一個(gè)List
),
);
}
}
這里我們創(chuàng)建的widget是一個(gè)StatefulWidget類型,因?yàn)檫@里我們需要通過觸發(fā)onTap:后修改索引來動態(tài)的修改body部分的內(nèi)容。關(guān)于StatelessWidget和StatefulWidget的介紹,請點(diǎn)擊這里。
接下來看下pages文件夾
這里面的4個(gè)dart 文件的內(nèi)容都是一致的,這也是我們在之后的開發(fā)中具體要實(shí)現(xiàn)的部分。他們都是StatefulWidget類型。我們就拿pend_course.dart看下
// 待上課程
import 'package:flutter/material.dart';
class PendCourse extends StatefulWidget {
@override
_PendCourseState createState() => _PendCourseState();
}
class _PendCourseState extends State<PendCourse> {
@override
Widget build(BuildContext context) {
return Scaffold( //這里還是一個(gè)Scaffold
appBar: AppBar( //navigationBar
title: Text('待上課程'), //navigationBar.title (這里其實(shí)可以出入任意widget)
// * 這里我就給了一個(gè)Text (UILabel)
),
body: Center( //self.view 部分
child: Text('澤澤1'), //UILabel 這里也是任意Widget,這里是subViews部分
),
);
}
}
總結(jié)
本篇文章并沒有太多的概念,就是通過代碼看下在flutter中tabbar結(jié)構(gòu)頁面的實(shí)現(xiàn),在flutter的UI層,各種widget的組合還是非常靈活的,再配合上Hod reload,效率真是杠杠的!不得不贊一個(gè)。