我们在使用大多数应用类APP的时候都会发现几乎每个APP底部都有导航栏,比如微信下面有聊天、通讯录、发现、我的这几个导航标签,可以快速的定位到对应的功能页面,而且我们会发现底部导航标签引导的区域基本是相对独立的,也就是说每一个导航功能对应的都是各自要展现的独立内容。这个功能的实现需要用到flutter里的BottonNavigationBar这个控件。
项目说明:实现一个底部导航栏,包含3到4个功能标签,点击对应的导航标签可以切换到对应的页面内容,并且页面抬头显示的内容也会跟着改变。
实际上由于手机屏幕大小的限制,底部导航栏的功能标签一般在3到5个左右,如果太多,会比较拥挤,影响用户体验,实际上目前市面上大多数APP的底部导航标签都控制在4到5个左右。既美观、又不会让用户觉得功能繁杂。
下面撸码:
首先我们新建一个底部导航控件,由于点击导航标签的时候页面内容是会发生改变的,所以这是一个有状态的控件。
import 'package:flutter/material.dart';
class BottomNavigationWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new BottomNavigationWidgetState();
}
}
class BottomNavigationWidgetState extends State<BottomNavigationWidget> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
/*
返回一个脚手架,里面包含两个属性,一个是底部导航栏,另一个就是主体内容
*/
return new Scaffold(
bottomNavigationBar: BottomNavigationBar(
//底部导航栏的创建需要对应的功能标签作为子项,这里我就写了3个,每个子项包含一个图标和一个title。
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: new Text(
'首页',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.business,
),
title: new Text(
'商业',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.mood,
),
title: new Text(
'我的',
)),
],
//这是底部导航栏自带的位标属性,表示底部导航栏当前处于哪个导航标签。给他一个初始值0,也就是默认第一个标签页面。
currentIndex: _currentIndex,
//这是点击属性,会执行带有一个int值的回调函数,这个int值是系统自动返回的你点击的那个标签的位标
onTap: (int i) {
//进行状态更新,将系统返回的你点击的标签位标赋予当前位标属性,告诉系统当前要显示的导航标签被用户改变了。
setState(() {
_currentIndex = i;
});
},
),
);
}
}
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: '底部导航演示',
home: new BottomNavigationWidget(),
);
}
}
运行后你会发现显示效果如下,点击底部标签会有一个颜色状态的变化:
Screenshot_1538049889.png Screenshot_1538049891.png
到这里其实基本实现了底部导航栏的功能,下面我们增加点击导航标签,对应的上面内容也会随着变化。
首先我们新建3个dart文件,用于新建3个主体展示页面,这三个页面都是带一个appbar和body,appbar用于显示对应的导航标签,body里显示对应的他们的标签大图标。三个文件的写法基本是一致的。
第一个 HomePAGE:
import 'package:flutter/material.dart';
class HomePageWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new HomePageWidgetState();
}
}
class HomePageWidgetState extends State<HomePageWidget>{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('首页'),
),
body: new Center(
child: Icon(Icons.home,size: 130.0,color: Colors.blue,),
),
);
}
}
第二个 BusinessPage:
import 'package:flutter/material.dart';
class BusinessPageWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new BusinessPageWidgetState();
}
}
class BusinessPageWidgetState extends State<BusinessPageWidget>{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('商业'),
),
body: new Center(
child: Icon(Icons.business,size: 130.0,color: Colors.blue,),
),
);
}
}
第三个 Mypage:
import 'package:flutter/material.dart';
class MyPageWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return new MyPageWidgetState();
}
}
class MyPageWidgetState extends State<MyPageWidget>{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('我的'),
),
body: new Center(
child: Icon(Icons.mood,size: 130.0,color: Colors.blue,),
),
);
}
}
然后回到底部导航栏文件,我们需要导入这3个页面文件:
import 'homePage.dart';
import 'businessPage.dart';
import 'myPage.dart';
由于在点击导航标签的时候要能对应改变上面主体内容,而且显示的内容是要和点击的导航标签相对应,所以我们这里还是通过位标来实现,因为每个导航标签是有一个位标的,那么只要我们点击标签的那个位标等同于要展示页面的值,就会对应显示了。所以我们可以把三个页面放在一个List里:
List<Widget> pages = new List();
@override
//initState是初始化函数,在绘制底部导航控件的时候就把这3个页面添加到list里面用于下面跟随标签导航进行切换显示
void initState() {
pages
..add(HomePageWidget())
..add(BusinessPageWidget())
..add(MyPageWidget());
}
然后在底部导航栏的Scaffold中的body配置跟随导航标签要显示的页面:
//主体显示的页面跟随当前导航标签的位标值在pages页面列表中选择。
body: pages[_currentIndex]
程序跑起来点击导航标签显示如下:
底部导航.gif
=============================我割===========================
上面已经把本次练习的主要目的底部导航实现了,但是关于底部导航的一些显示小细节就是关于点击的效果这里也给大家大家举个例子:
一个就是上面那种默认图标、标题都存在,点击对应的标签颜色变化。
还有一种就是默认只显示图标,只有在点击后才会显示标题,而且会有一个小的动画效果,这个就要用到底部导航的的type属性:
type: BottomNavigationBarType.shifting
但是使用这个以后由于我之前的代码没有给图标和标题设置颜色,所以是一片白色,想要尝试的朋友记得设置图标颜色,我设置成色以后点击效果就是这样的:
底部导航-2.gif
你觉得两种效果哪种更好看呢?
网友评论