我們?cè)谑褂么蠖鄶?shù)應(yīng)用類APP的時(shí)候都會(huì)發(fā)現(xiàn)幾乎每個(gè)APP底部都有導(dǎo)航欄圃郊,比如微信下面有聊天甫男、通訊錄且改、發(fā)現(xiàn)、我的這幾個(gè)導(dǎo)航標(biāo)簽板驳,可以快速的定位到對(duì)應(yīng)的功能頁面又跛,而且我們會(huì)發(fā)現(xiàn)底部導(dǎo)航標(biāo)簽引導(dǎo)的區(qū)域基本是相對(duì)獨(dú)立的,也就是說每一個(gè)導(dǎo)航功能對(duì)應(yīng)的都是各自要展現(xiàn)的獨(dú)立內(nèi)容笋庄。這個(gè)功能的實(shí)現(xiàn)需要用到flutter里的BottonNavigationBar這個(gè)控件效扫。
項(xiàng)目說明:實(shí)現(xiàn)一個(gè)底部導(dǎo)航欄,包含3到4個(gè)功能標(biāo)簽直砂,點(diǎn)擊對(duì)應(yīng)的導(dǎo)航標(biāo)簽可以切換到對(duì)應(yīng)的頁面內(nèi)容菌仁,并且頁面抬頭顯示的內(nèi)容也會(huì)跟著改變。
實(shí)際上由于手機(jī)屏幕大小的限制静暂,底部導(dǎo)航欄的功能標(biāo)簽一般在3到5個(gè)左右济丘,如果太多,會(huì)比較擁擠洽蛀,影響用戶體驗(yàn)摹迷,實(shí)際上目前市面上大多數(shù)APP的底部導(dǎo)航標(biāo)簽都控制在4到5個(gè)左右。既美觀郊供、又不會(huì)讓用戶覺得功能繁雜峡碉。
下面擼碼:
首先我們新建一個(gè)底部導(dǎo)航控件,由于點(diǎn)擊導(dǎo)航標(biāo)簽的時(shí)候頁面內(nèi)容是會(huì)發(fā)生改變的驮审,所以這是一個(gè)有狀態(tài)的控件鲫寄。
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) {
/*
返回一個(gè)腳手架,里面包含兩個(gè)屬性疯淫,一個(gè)是底部導(dǎo)航欄地来,另一個(gè)就是主體內(nèi)容
*/
return new Scaffold(
bottomNavigationBar: BottomNavigationBar(
//底部導(dǎo)航欄的創(chuàng)建需要對(duì)應(yīng)的功能標(biāo)簽作為子項(xiàng),這里我就寫了3個(gè)熙掺,每個(gè)子項(xiàng)包含一個(gè)圖標(biāo)和一個(gè)title未斑。
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: new Text(
'首頁',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.business,
),
title: new Text(
'商業(yè)',
)),
BottomNavigationBarItem(
icon: Icon(
Icons.mood,
),
title: new Text(
'我的',
)),
],
//這是底部導(dǎo)航欄自帶的位標(biāo)屬性,表示底部導(dǎo)航欄當(dāng)前處于哪個(gè)導(dǎo)航標(biāo)簽币绩。給他一個(gè)初始值0蜡秽,也就是默認(rèn)第一個(gè)標(biāo)簽頁面府阀。
currentIndex: _currentIndex,
//這是點(diǎn)擊屬性,會(huì)執(zhí)行帶有一個(gè)int值的回調(diào)函數(shù)载城,這個(gè)int值是系統(tǒng)自動(dòng)返回的你點(diǎn)擊的那個(gè)標(biāo)簽的位標(biāo)
onTap: (int i) {
//進(jìn)行狀態(tài)更新肌似,將系統(tǒng)返回的你點(diǎn)擊的標(biāo)簽位標(biāo)賦予當(dāng)前位標(biāo)屬性费就,告訴系統(tǒng)當(dāng)前要顯示的導(dǎo)航標(biāo)簽被用戶改變了诉瓦。
setState(() {
_currentIndex = i;
});
},
),
);
}
}
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: '底部導(dǎo)航演示',
home: new BottomNavigationWidget(),
);
}
}
運(yùn)行后你會(huì)發(fā)現(xiàn)顯示效果如下,點(diǎn)擊底部標(biāo)簽會(huì)有一個(gè)顏色狀態(tài)的變化:
到這里其實(shí)基本實(shí)現(xiàn)了底部導(dǎo)航欄的功能力细,下面我們?cè)黾狱c(diǎn)擊導(dǎo)航標(biāo)簽睬澡,對(duì)應(yīng)的上面內(nèi)容也會(huì)隨著變化。
首先我們新建3個(gè)dart文件眠蚂,用于新建3個(gè)主體展示頁面煞聪,這三個(gè)頁面都是帶一個(gè)appbar和body,appbar用于顯示對(duì)應(yīng)的導(dǎo)航標(biāo)簽逝慧,body里顯示對(duì)應(yīng)的他們的標(biāo)簽大圖標(biāo)昔脯。三個(gè)文件的寫法基本是一致的。
第一個(gè) 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,),
),
);
}
}
第二個(gè) 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('商業(yè)'),
),
body: new Center(
child: Icon(Icons.business,size: 130.0,color: Colors.blue,),
),
);
}
}
第三個(gè) 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,),
),
);
}
}
然后回到底部導(dǎo)航欄文件笛臣,我們需要導(dǎo)入這3個(gè)頁面文件:
import 'homePage.dart';
import 'businessPage.dart';
import 'myPage.dart';
由于在點(diǎn)擊導(dǎo)航標(biāo)簽的時(shí)候要能對(duì)應(yīng)改變上面主體內(nèi)容云稚,而且顯示的內(nèi)容是要和點(diǎn)擊的導(dǎo)航標(biāo)簽相對(duì)應(yīng),所以我們這里還是通過位標(biāo)來實(shí)現(xiàn)沈堡,因?yàn)槊總€(gè)導(dǎo)航標(biāo)簽是有一個(gè)位標(biāo)的静陈,那么只要我們點(diǎn)擊標(biāo)簽的那個(gè)位標(biāo)等同于要展示頁面的值,就會(huì)對(duì)應(yīng)顯示了诞丽。所以我們可以把三個(gè)頁面放在一個(gè)List里:
List<Widget> pages = new List();
@override
//initState是初始化函數(shù)鲸拥,在繪制底部導(dǎo)航控件的時(shí)候就把這3個(gè)頁面添加到list里面用于下面跟隨標(biāo)簽導(dǎo)航進(jìn)行切換顯示
void initState() {
pages
..add(HomePageWidget())
..add(BusinessPageWidget())
..add(MyPageWidget());
}
然后在底部導(dǎo)航欄的Scaffold中的body配置跟隨導(dǎo)航標(biāo)簽要顯示的頁面:
//主體顯示的頁面跟隨當(dāng)前導(dǎo)航標(biāo)簽的位標(biāo)值在pages頁面列表中選擇。
body: pages[_currentIndex]
程序跑起來點(diǎn)擊導(dǎo)航標(biāo)簽顯示如下:
=============================我割===========================
上面已經(jīng)把本次練習(xí)的主要目的底部導(dǎo)航實(shí)現(xiàn)了僧免,但是關(guān)于底部導(dǎo)航的一些顯示小細(xì)節(jié)就是關(guān)于點(diǎn)擊的效果這里也給大家大家舉個(gè)例子:
一個(gè)就是上面那種默認(rèn)圖標(biāo)刑赶、標(biāo)題都存在,點(diǎn)擊對(duì)應(yīng)的標(biāo)簽顏色變化懂衩。
還有一種就是默認(rèn)只顯示圖標(biāo)撞叨,只有在點(diǎn)擊后才會(huì)顯示標(biāo)題,而且會(huì)有一個(gè)小的動(dòng)畫效果勃痴,這個(gè)就要用到底部導(dǎo)航的的type屬性:
type: BottomNavigationBarType.shifting
但是使用這個(gè)以后由于我之前的代碼沒有給圖標(biāo)和標(biāo)題設(shè)置顏色谒所,所以是一片白色,想要嘗試的朋友記得設(shè)置圖標(biāo)顏色沛申,我設(shè)置成色以后點(diǎn)擊效果就是這樣的:
你覺得兩種效果哪種更好看呢劣领?