Flutter中的底部导航和顶部导航

BottomNavigatorBar

Flutter中实现底部导航需要在Scaffold脚手架中赋值bottomNavigationBar参数,这个参数接受一个Widget,一般我们直接赋值BottomNavigationBar对象。

其中有几个参数比较重要

  • currentIndex

    当前item元素的索引

  • onTap

    当点击的时候触发的函数

  • items

    存放路由导航的的按钮(小部件)。

    需要注意的是整个脚手架需要放置在动态组件中。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class MyScaffold extends StatefulWidget {
@override
_MyScaffoldState createState() => _MyScaffoldState();
}

class _MyScaffoldState extends State<MyScaffold> {
int _currentIndex = 0;

// 定义导航切换的路由
List<Widget> _tabsWidget = [TabControllerPage(), MyMessage(), MySetting()];

@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Tab Demo'),
leading: IconButton(icon: Icon(Icons.favorite), onPressed: () {}),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: this._currentIndex,
// 触发重构页面
onTap: (index) => setState(() => this._currentIndex = index),
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('home')),
BottomNavigationBarItem(
icon: Icon(Icons.message), title: Text('message')),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text('settings'))
],
),
body: _tabsWidget[this._currentIndex],
),
);
}
}

TabBar

TabBar是用来实现顶部滑动导航的。我们可以放置在脚手架中appBar中的bottom中。

但最需要注意的是我们需要在脚手架外层嵌套一个DefaultTabController,我们必须要定义这个组件中的length属性,这是用来定义导航条的数目的。然后我们再bottom中定义一个TabBar,里面的tabs属性接受一个Widget数组,数组中存放导航条,然后我们可以在Scaffold中的body里面添加TabBarView,TabBarView里面有children属性,是用来存放导航的主页面的,所以我们这里DefaultTabController中的length属性和bottom中tabs中数组的长度还有这个children数组的长度,三者必须一样。

其实这里就是在你想要实现顶部导航页面外层嵌套DefaultTabController并且定义长度,然后再里面定义TabBar和TabBarView,这个DefaultTabController用来对TabBar和TabBarView进行”连接”和监听。

常规顶部导航代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class MyScaffold extends StatefulWidget {
@override
_MyScaffoldState createState() => _MyScaffoldState();
}

class _MyScaffoldState extends State<MyScaffold> {

@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Tab Demo'),
leading: IconButton(icon: Icon(Icons.favorite), onPressed: () {}),
bottom: TabBar(
isScrollable: true,
tabs: <Widget>[
Tab(
text: 'hot',
),
Tab(
text: 'recommend',
)
],
),
),
body: TabBarView(
children: <Widget>[
ListView(
children: <Widget>[
ListTile(
title: Text('111111'),
),
ListTile(
title: Text('222222'),
),
ListTile(
title: Text('333333'),
),
],
),
ListView(
children: <Widget>[
ListTile(
title: Text('111111'),
),
ListTile(
title: Text('222222'),
),
ListTile(
title: Text('333333'),
),
],
),
],
),
),
);
}
}

如果我们页面里面已经有底层导航了,这时候我们就不同在appBar中的bottom属性中存放导航条了。

比如你现在有三个底部导航路由,然后你在总的Scaffold中的appBar中添加顶部导航栏,这样就会使你的底部三个页面都存在这个顶部导航栏。

如果你在另一个页面再次使用Scaffold构建子页面 你可以做在appBar的title中定义TabBar,appBar的title属性接受一个Widget,你可以将TabBar赋值给它。或者你可以在新建的脚手架中不使用appBar属性。

自定义TabBar

我们需要在一个动态组件中创建一个TabController 然后这个组件需要with(类似多继承)一个SingleTickerProviderStateMixin(用来设置TabController中的vsync垂直同步属性的)。然后我们这时候不需要使用DefaultTabController来嵌套组件了,我们只需要在TabBar和TabBarView组件中定义他们的Controller属性为我们的controller,当然我们需要在init组件的时候创建controller。

使用自定义的好处就是我们可以监听controller的状态从而定制一些个性化的操作。

自定义TabController代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import 'package:flutter/material.dart';

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

_AppBardemoPageState createState() => _AppBardemoPageState();
}

class _AppBardemoPageState extends State<AppBardemoPage>
with SingleTickerProviderStateMixin {
TabController _tabController;

@override
void dispose() {
_tabController.dispose();
super.dispose();
}

void initState() {
super.initState();
_tabController = new TabController(vsync: this, length: 3);
// 我们这时候可以添加监听器来实现自定义
_tabController.addLinstener((){
// 获取控制器的一些值来改变一些UI组件
print(_tabController.index);
});
}

@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('顶部 tab 切换'), bottom: new TabBar(
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.directions_bike),), new Tab(
icon: new Icon(Icons.directions_boat),), new Tab(
icon: new Icon(Icons.directions_bus),),
], controller: _tabController,),), body: new TabBarView(
controller: _tabController, children: <Widget>[
new Center(child: new Text('自行车')),
new Center(child: new Text('船')),
new Center(child: new Text('巴士')),
],),);
}
-------------本文结束感谢阅读-------------