Flutter BottomNavigationBar 实现底部 Tab 导航
一、Scalfold 页面结构
之前 Flutter 基本页面结构布局 及 自定义 Widget 文件 分离 这篇文章提到了 Scalfold Widget
是用来描述页面的主结构
一个 MaterialApp
由多个 Scalfold
页面组成,每个 Scalfold
的普遍结果如下:
- AppBar:顶部导航栏
- body:中间内容体
- BottomNavigationBar:底部导航栏
当然除了上面,还有 drawer
和 floatingButton
等
这些都是可以省略的,这点从 Scalfold 构造函数就能看出:
const Scaffold({
Key key,
this.appBar,
this.body,
this.floatingActionButton,
this.floatingActionButtonLocation,
this.floatingActionButtonAnimator,
this.persistentFooterButtons,
this.drawer,
this.endDrawer,
this.bottomNavigationBar,
this.bottomSheet,
this.backgroundColor,
this.resizeToAvoidBottomPadding,
this.resizeToAvoidBottomInset,
this.primary = true,
this.drawerDragStartBehavior = DragStartBehavior.start,
this.extendBody = false,
this.drawerScrimColor,
}) : assert(primary != null),
assert(extendBody != null),
assert(drawerDragStartBehavior != null),
super(key: key);
关于 AppBar 和 body 可以看上面的文章怎么使用,不再重复,这里主要是是 bottomNavigationBar
的配置和使用
bottomNavigationBar
的类型是 Widget BottomNavigationBar
,构造函数如下:
BottomNavigationBar({
Key key,
@required this.items,
this.onTap,
this.currentIndex = 0,
this.elevation = 8.0,
BottomNavigationBarType type,
Color fixedColor,
this.backgroundColor,
this.iconSize = 24.0,
Color selectedItemColor,
this.unselectedItemColor,
this.selectedIconTheme = const IconThemeData(),
this.unselectedIconTheme = const IconThemeData(),
this.selectedFontSize = 14.0,
this.unselectedFontSize = 12.0,
this.selectedLabelStyle,
this.unselectedLabelStyle,
this.showSelectedLabels = true,
bool showUnselectedLabels,
})
从上面看出,items
是必填的属性参数,也就是一个 BottomNavigationBarItem
Widget 列表,定义如下:
/// Defines the appearance of the button items that are arrayed within the
/// bottom navigation bar.
final List<BottomNavigationBarItem> items;
其他几个经常用到的参数是:
- onTap: 处理 tab 的点击事件
- currentIndex:当前那个 tab 是 active 状态的
还有都是指定样式的了
二、BottomNavigationBar 实现底部 tab 导航
1、准备三个页面
首先 Tab 切换 切换的是页面,因此我们需要准备几个 Page,几个 Page 就很简单,就是显示文字
1)首页
// 首页页面
class HomePage extends StatelessWidget {
const HomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return PageContent(title: '首页');
}
}
2)新闻页
// 新闻页面
class NewsPage extends StatelessWidget {
const NewsPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return PageContent(title: '新闻');
}
}
最终放到一个列表中:
List<Widget> _pageList = [
HomePage(),
NewsPage(),
MyPage(),
];
3)我的
// 我的页面
class MyPage extends StatelessWidget {
const MyPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return PageContent(title: '我的');
}
}
2、配置 BottomNavigationBar.items
每个 Tab 子项和我们的页面是一一对应的,三个页面需要构造三个 BottomNavigationBarItem
BottomNavigationBarItem
构造函数很简单:
const BottomNavigationBarItem({
@required this.icon,
this.title,
Widget activeIcon,
this.backgroundColor,
}) : activeIcon = activeIcon ?? icon,
assert(icon != null);
icon
和 activeIcon
是两个状态下的图标,title 则是文本,只有默认的 icon 是必须的。
bottomNavigationBar.items
可以构造如下:
List<BottomNavigationBarItem> _barItem = [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')),
BottomNavigationBarItem(icon: Icon(Icons.list), title: Text('新闻')),
BottomNavigationBarItem(icon: Icon(Icons.people), title: Text('我的')),
];
3、配置 Scalfold.body
和 Scalfold.bottomNavigationBar
有了 bottomNavigationBar 的列表之后,我们直接进行配置,除此之外,我们需要一个变量来存储当前是访问的第几个 tab: int _currentIndex = 0;
currentIndex: _currentIndex,
items: _barItem,
fixedColor: Colors.pink,
selectedFontSize: 12,
type: BottomNavigationBarType.fixed,
配置好 items
和 currentIndex
属性之外,我们需要处理点击事件 onTap
:
onTap: (int index) {
setState(() {
this._currentIndex = index;
});
},
每次点击,我们都动态的切换当前的 index,也就是 currentIndex,因此需要我们的 Wdiget 是 StatefulWidget
类型。
现在我们点击能够动态的切换 index,然后我们准备好了 page 的列表,之前我们渲染一个页面都是直接在 body 中配置一个 Widget
比如这种写法:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Card Widget'),
backgroundColor: Colors.pink,
),
body: HomeContent(),
),
);
}
}
导航的切换时需要动态的变更 主页 body 的内容,因此需要动态的配置 body 的组件:
body: this._pageList[this._currentIndex],
4、完整的页面
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int _currentIndex = 0;
List<Widget> _pageList = [
HomePage(),
NewsPage(),
MyPage(),
];
List<BottomNavigationBarItem> _barItem = [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')),
BottomNavigationBarItem(icon: Icon(Icons.list), title: Text('新闻')),
BottomNavigationBarItem(icon: Icon(Icons.people), title: Text('我的')),
];
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('BottomNavigationBar'),
backgroundColor: Colors.pink,
),
body: this._pageList[this._currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: (int index) {
setState(() {
this._currentIndex = index;
});
},
currentIndex: this._currentIndex,
items: _barItem,
fixedColor: Colors.pink,
selectedFontSize: 12,
type: BottomNavigationBarType.fixed,
),
),
);
}
}
三、最终效果
四、代码
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://www.ptbird.cn/flutter-bottomnavigatorbar-tab.html
转载请注明文章原始出处 !