区别
BottomNavigationBar
r和TabBar
都是用于创建导航栏的组件,但它们有一些区别。
-
位置不同:
BottomNavigationBar
通常位于屏幕底部,用于主要导航;而TabBar
通常位于屏幕顶部或底部,用于切换不同的视图或页面。 -
样式不同:
BottomNavigationBar
是一个水平的导航栏,通常包含固定数量的图标和标签。它提供了固定的样式,并且可以自动处理选中和未选中状态的切换。TabBar
可以水平或垂直显示,通常用于展示多个选项卡。它提供了更多的自定义选项,比如可以设置自定义的标签样式、背景色等。 -
功能不同:
BottomNavigationBa
r通常用于在不同的主页面之间进行导航,每个图标对应一个页面。它的功能相对简单,适用于主要导航。TabBar
用于切换不同的视图或页面,并且可以与TabBarView
一起使用来展示与每个选项卡对应的内容。它在应用程序中的使用场景更加广泛,适用于切换和展示多个相关页面或功能。
总之,BottomNavigationBar
适用于简单的主导航,TabBar
适用于更复杂的页面切换和内容展示。
示例:来源于qq阅读
BottomNavigationBar
TabBar
BottomNavigationBar
BottomNavigationBar
是Flutter中用于创建底部导航栏的组件。它通常与TabBarView
一起使用,用于在不同的选项卡之间切换内容。
BottomNavigationBar
有一个items属性,其中可以定义导航栏的每个选项卡。每个选项卡都可以包含一个图标和一个文本标签。
class SwitcherContainer extends StatefulWidget {
const SwitcherContainer({Key? key}) : super(key: key);
SwitcherContainerState createState() => SwitcherContainerState();
}
class SwitcherContainerState extends State<SwitcherContainer> {
String name = '首页';
List<String> nameList = ['首页', '书籍', '我的'];
// 激活项
int _currentIndex = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('导航'),
),
body: Center(
child: Text(name),
),
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(label: '首页', icon: Icon(Icons.home)),
BottomNavigationBarItem(label: '书籍', icon: Icon(Icons.book)),
BottomNavigationBarItem(label: '我的', icon: Icon(Icons.perm_identity)),
],
currentIndex: _currentIndex,
// 激活颜色
selectedItemColor: Colors.orange,
// 点击事件
onTap: (index) {
setState(() {
_currentIndex = index;
name = nameList[index];
});
},
),
);
}
}
如果没有特殊需求的话,使用系统提供的就可以。如果想要点不太一样的可以看一下下面这两个库:
- curved_navigation_bar
- google_nav_bar
curved_navigation_bar
一个易于实现曲面导航条
官方地址
https://pub-web.flutter-io.cn/packages/curved_navigation_bar
安装
flutter pub add curved_navigation_bar
简单使用
class SwitcherContainerState extends State<SwitcherContainer> {
String name = '首页';
List<String> nameList = ['首页', '书籍', '我的'];
// 激活项
int _currentIndex = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('导航'),
),
body: Stack(
children: [
Container(
color: Colors.blueAccent,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: null,
),
Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 150,
child: Text(name),
)
],
),
bottomNavigationBar: CurvedNavigationBar(
items: const [
Icon(Icons.home),
Icon(Icons.book),
Icon(Icons.perm_identity)
],
height: 60,
backgroundColor: Colors.blueAccent,
//激活项
index: _currentIndex,
// 点击事件
onTap: (index) {
setState(() {
_currentIndex = index;
name = nameList[index];
});
},
),
);
}
}
这个最好像我上面那样再调整一下,不然有点奇怪,比如:
bottom_navy_bar
一个美丽而生动的底部导航。导航栏使用您当前的主题,但您可以自由自定义
官方地址
https://pub-web.flutter-io.cn/packages/bottom_navy_bar
安装
flutter pub add bottom_navy_bar
简单使用
class SwitcherContainerState extends State<SwitcherContainer> {
String name = '首页';
List<String> nameList = ['首页', '书籍', '我的'];
// 激活项
int _currentIndex = 0;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('导航'),
),
body: Center(
child: Text(name),
),
bottomNavigationBar: BottomNavyBar(
// 当前选中项
selectedIndex: _currentIndex,
// 列表
items: [
BottomNavyBarItem(
textAlign: TextAlign.center,
icon: const Icon(Icons.home),
title: const Text("首页")),
BottomNavyBarItem(
textAlign: TextAlign.center,
icon: const Icon(Icons.book),
title: const Text("书架")),
BottomNavyBarItem(
textAlign: TextAlign.center,
icon: const Icon(Icons.perm_identity),
title: const Text("我的"))
],
// 选中事件
onItemSelected: (index) => setState(() {
_currentIndex = index;
name = nameList[index];
})),
);
}
}
TabBar
在Flutter中,TabBar
是一个常用的小部件,用于创建一个具有选项卡的导航栏。它通常与TabBarView
一起使用,以实现在不同选项卡之间切换内容的功能。
TabBar
由TabBar
和TabBarView
两个关键组件组成。
TabBar
:TabBar
小部件定义了选项卡的外观和交互方式。它可以包含多个选项卡,每个选项卡都由一个Tab对象表示。可以通过设置controller
属性来指定与TabBarView
关联的TabController
,以便在选项卡之间进行切换。
TabBarView
:TabBarView``小部件是一个可滚动的容器,用于显示与当前选中选项卡相关联的内容。每个选项卡对应一个子小部件,并且可以通过设置
controller属性来与
TabBar`关联。
class SwitcherContainer extends StatefulWidget {
const SwitcherContainer({Key? key}) : super(key: key);
SwitcherContainerState createState() => SwitcherContainerState();
}
class SwitcherContainerState extends State<SwitcherContainer>
with SingleTickerProviderStateMixin {
// 控制器
late TabController tabController;
void initState() {
super.initState();
tabController = TabController(length: 3, vsync: this);
}
void dispose() {
super.dispose();
// 释放
tabController.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TabBar Demo'),
bottom: TabBar( // 使用TabBar作为AppBar的bottom属性
controller: tabController, // 关联TabController
tabs: const [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView( // 使用TabBarView作为body
controller: tabController, // 关联TabController
children: const [
Center(child: Text('Content of Tab 1')),
Center(child: Text('Content of Tab 2')),
Center(child: Text('Content of Tab 3')),
],
),
);
}
}
注意点:
- 在Flutter中,
TabBar
和TabBarView
之间的切换通常需要使用动画效果。为了实现这种动画效果,需要使用TickerProvider
,它提供了一个Ticker
对象,用于生成动画的时间。而SingleTickerProviderStateMixin
是一个实现了TickerProvider
的混合类。
或者
return Column(
children: [
TabBar(
controller: tabController,
indicatorColor: Colors.red, // 设置选中选项卡下方的指示器颜色
labelColor: Colors.blue, // 设置选中选项卡的文本颜色
unselectedLabelColor: Colors.grey, // 设置未选中选项卡的文本颜色
tabs: const [
Tab(
text: 'Home',
),
Tab(
text: 'Settings',
),
],
),
Expanded(
child: TabBarView(
controller: tabController,
children: const [
Center(
child: Text("Home"),
),
Center(
child: Text("Settings"),
)
],
),
),
],
);
如果需要 TabBar
和 TabBarView
联动,通常会创建一个 DefaultTabController
作为它们共同的父级组件,这样它们在执行时就会从组件树向上查找,都会使用我们指定的这个 DefaultTabController
。
class TabViewRoute2 extends StatelessWidget {
Widget build(BuildContext context) {
List tabs = ["新闻", "历史", "图片"];
return DefaultTabController(
length: tabs.length,
child: Scaffold(
appBar: AppBar(
title: Text("App Name"),
bottom: TabBar(
tabs: tabs.map((e) => Tab(text: e)).toList(),
),
),
body: TabBarView( //构建
children: tabs.map((e) {
return KeepAliveWrapper(
child: Container(
alignment: Alignment.center,
child: Text(e, textScaleFactor: 5),
),
);
}).toList(),
),
),
);
}
}
可以看到我们无需去手动管理 Controller
的生命周期,也不需要提供 SingleTickerProviderStateMixin
,同时也没有其他的状态需要管理,也就不需要用 StatefulWidget
了,这样简单很多
这里推荐一下:tab_indicator_styler
,这个库是用来修改指示器样式的
官方地址
https://pub-web.flutter-io.cn/packages/tab_indicator_styler
安装
flutter pub add tab_indicator_styler
基本使用
import 'package:tab_indicator_styler/tab_indicator_styler.dart';
Scaffold(
appBar: AppBar(
toolbarHeight: 10,
bottom: TabBar(
// 使用TabBar作为AppBar的bottom属性
controller: tabController, // 关联TabController
indicatorSize: TabBarIndicatorSize.tab, // 设置指示器宽度
// 指示器样式
indicator: MaterialIndicator(
height: 5,
topLeftRadius: 8,
topRightRadius: 8,
horizontalPadding: 50,
tabPosition: TabPosition.bottom,
color: Colors.white
),
tabs: const [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView(
// 使用TabBarView作为body
controller: tabController, // 关联TabController
children: const [
Center(child: Text('Content of Tab 1')),
Center(child: Text('Content of Tab 2')),
Center(child: Text('Content of Tab 3')),
],
),
);
注意:MaterialIndicator
风格的指示器的宽度必须使用indicatorSize: TabBarIndicatorSize.tab
,也就是默认值,否则会报错
indicator: DotIndicator(
radius: 5,
color: Colors.orange,
// 圆点距离文字的间距,正数在下面,负数在上面
distanceFromCenter: 20,
),
indicator: RectangularIndicator(
bottomLeftRadius: 30,
bottomRightRadius: 30,
topLeftRadius: 30,
topRightRadius: 30,
),