BottomNavigationBar尝试 2023-08-16
2023-08-17 本文已影响0人
勇往直前888
简介
工具类的首页,大多数都做成tab
切换的样子。
实现方案
-
Scaffold
框架有一个属性Widget? bottomNavigationBar,
就是专门做这个的。 -
方案1:类型是
Widget?
,其实不大准确;大多数时候,这里都会给一个BottomNavigationBar
。 -
方案2:当然,约束条件松一点,可以自己用
Container
模仿一个,那么实现起来就更自由了。 -
如果没有特殊的要求,直接使用
BottomNavigationBar
是最简单的。
底部实现
-
BottomNavigationBar
要结合BottomNavigationBarItem
一起用,一个图标,一个文本,最常用的模式
Scaffold(
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(title: Text('首页'),icon: Icon(Icons.home)),
BottomNavigationBarItem(title: Text('书籍'),icon: Icon(Icons.book)),
BottomNavigationBarItem(title: Text('我的'),icon: Icon(Icons.perm_identity)),
],
),
);
- 选中,通过
currentIndex
属性设置当前选中的BottomNavigationBarItem
;要注意的事这里只是底部按钮的选中状态,页面内容并不会变化。
页面切换
方案1:页面切换
int _currentIndex = 0;
Widget _currBody = HomePage();
_onTap(int index) {
switch (index) {
case 0:
_currBody = HomePage();;
break;
case 1:
_currBody = BookPage();
break;
case 2:
_currBody = MyPage();
break;
}
setState(() {
_currentIndex = index;
});
}
Scaffold(
body: _currBody,
bottomNavigationBar: BottomNavigationBar(
onTap: _onTap,
type: BottomNavigationBarType.shifting,
selectedItemColor: Theme.of(context).primaryColor,
unselectedItemColor: Colors.black,
currentIndex: _currentIndex,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(title: Text('首页'), icon: Icon(Icons.home)),
BottomNavigationBarItem(title: Text('书籍'), icon: Icon(Icons.book)),
BottomNavigationBarItem(
title: Text('我的'), icon: Icon(Icons.perm_identity)),
],
),
);
这个通过Switch语句,进行切换,问题是页面不断重建,不能保持状态
Flutter Widgets 之 BottomNavigationBar
方案2:数组
import 'package:flutter/material.dart';
import 'tabs/Category.dart';
import 'tabs/Email.dart';
import 'tabs/Home.dart';
import 'tabs/Setting.dart';
class Tabs extends StatefulWidget {
const Tabs({Key? key}) : super(key: key);
@override
_TabsState createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
int currentIndex = 0;
List _pageList = [HomePage(), CategoryPage(), SettingPage(), EmailPage()];
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: _pageList[currentIndex],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: currentIndex,
onTap: (int index) {
setState(() {
currentIndex = index;
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "首页",
),
BottomNavigationBarItem(
icon: Icon(Icons.category), title: Text("分类")),
BottomNavigationBarItem(icon: Icon(Icons.mail), title: Text("邮件")),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text("设置")),
],
),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
这里把页面保存在一个数组中,避免了页面频繁重建,也能保持状态。
Flutter BottomNavigationBar组件
方案3:IndexedStack
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
var pages = [
WeiChatPage(),
DevicePage(),
MinePage()
];
var titles = ["首页","设备","我的"];
var currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leadingWidth: 70,
leading: currentIndex == 1 ? TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.only(left: 10)),
),
onPressed: (){},
child: Text("切换设备",style: TextStyle(
color: Colors.black,
fontSize: 14
),),
) : null,
actions: currentIndex == 1 ? [
IconButton(onPressed: (){}, icon: Icon(Icons.add,color: Colors.black,))
] : null,
backgroundColor: Colors.white,
elevation: 0.2,
centerTitle: true,
title: Text(titles[currentIndex],style: TextStyle(
color: Colors.black
),),
),
body: IndexedStack( /// 在这里修改
index: currentIndex,
children: pages,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
type: BottomNavigationBarType.fixed,
onTap: (index) {
setState(() {
currentIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.messenger_outlined),
label:titles[0]),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: titles[1]),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: titles[2]),
],
),
);
}
}
这个也用一个数组保存了页面,有缓存,能保持状态,并且封装成了组件,感觉是最匹配的。
Flutter BottomNavigationBar 页面缓存
小结
-
如果能满足要求,直接使用
BottomNavigationBar
+IndexedStack
的组合是最方便的; -
对于自定义,还是用
Container()
来模拟比较好