Flutter持久化底部导航栏插件persistent_bottom_nav_bar_2的使用
Flutter 持久化底部导航栏插件 persistent_bottom_nav_bar_2 的使用
Persistent Bottom Navigation Bar
一个用于 Flutter 的持久化底部导航栏。
注意:那些从 <strong>pre 2.0.0</strong>
版本迁移的人应该查看最新的文档和说明,因为 2.0.0 更新引入了许多破坏性的更改。
[持久行为]
样式
样式15 | 样式16 |
---|---|
[样式1] | [样式10] |
样式1 | 样式9 |
---|---|
[样式1] | [样式10] |
样式7 | 样式10 |
---|---|
[样式3] | [样式5] |
样式12 | 样式13 |
---|---|
[样式6] | [样式8] |
样式3 | 样式6 |
---|---|
[样式6] | [样式8] |
浮雕 | 浮雕无副标题 |
---|---|
[浮雕1] | [浮雕2] |
注意:这些并不包括所有样式变化
功能
- 高度可定制的持久底部导航栏。
- 可以推送到新屏幕,并且可以有或没有底部导航栏。
- 底部导航栏有 20 种样式。
- 包含用于推送新屏幕的函数,可以选择是否包含底部导航栏,例如
pushNewScreen()
和pushNewScreenWithRouteSettings()
。 - 基于 Flutter 的 Cupertino(iOS)底部导航栏。
- 可以为特定标签设置为半透明。
- 可以自定义导航栏的样式。更多信息请参见自定义导航栏样式。
- 处理硬件/软件 Android 返回按钮。
开始使用
在你的 Flutter 项目中添加依赖:
dependencies:
persistent_bottom_nav_bar: any
导入包:
import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart';
持久底部导航栏使用 PersistentTabController
作为控制器。声明如下:
PersistentTabController _controller;
_controller = PersistentTabController(initialIndex: 0);
主要要声明的 widget 是 PersistentTabView
。注意,这个 widget 包括 SCAFFOLD(基于 CupertinoTabScaffold
),所以不需要单独声明它。以下是一个示例:
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return PersistentTabView(
context,
controller: _controller,
screens: _buildScreens(),
items: _navBarsItems(),
confineInSafeArea: true,
backgroundColor: Colors.white, // 默认值为 Colors.white。
handleAndroidBackButtonPress: true, // 默认值为 true。
resizeToAvoidBottomInset: true, // 如果希望键盘出现时移动屏幕,则需要设置为 true。默认值为 true。
stateManagement: true, // 默认值为 true。
hideNavigationBarWhenKeyboardShows: true, // 推荐将 `resizeToAvoidBottomInset` 设置为 true 来使用此参数。默认值为 true。
decoration: NavBarDecoration(
borderRadius: BorderRadius.circular(10.0),
colorBehindNavBar: Colors.white,
),
popAllScreensOnTapOfSelectedTab: true,
popActionScreens: PopActionScreensType.all,
itemAnimationProperties: ItemAnimationProperties( // 导航栏项目的动画属性。
duration: Duration(milliseconds: 200),
curve: Curves.ease,
),
screenTransitionAnimation: ScreenTransitionAnimation( // 选择的标签切换时的屏幕过渡动画。
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
navBarStyle: NavBarStyle.style1, // 使用此属性选择导航栏样式。
);
}
}
List<Widget> _buildScreens() {
return [
MainScreen(),
SettingsScreen()
];
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
icon: Icon(CupertinoIcons.home),
title: ("Home"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
PersistentBottomNavBarItem(
icon: Icon(CupertinoIcons.settings),
title: ("Settings"),
activeColorPrimary: CupertinoColors.activeBlue,
inactiveColorPrimary: CupertinoColors.systemGrey,
),
];
}
导航器功能
注意:你仍然可以使用常规的 Navigator 函数,如 ‘pushNamed’,但请确保检查你的 PersistentBottomNavBarItem
的 routeAndNavigatorSettings
参数中的路由设置和其他导航相关属性。
要推送新屏幕,可以使用以下函数来控制某个屏幕上的底部导航栏的可见性。你可以使用自己的逻辑来实现平台特定的行为。一种解决方案是使用 withNavBar
属性并根据平台进行切换。
在平台特定的行为中,当推送新屏幕时,在 Android 上会推送没有底部导航栏的屏幕,但在 iOS 上会保持底部导航栏。这是每个平台的默认行为。
PersistentNavBarNavigator.pushNewScreen(
context,
screen: MainScreen(),
withNavBar: true, // 可选值,默认为 true。
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
PersistentNavBarNavigator.pushNewScreenWithRouteSettings(
context,
settings: RouteSettings(name: MainScreen.routeName),
screen: MainScreen(),
withNavBar: true,
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
如果你要推送新的模态屏幕,使用以下函数:
PersistentNavBarNavigator.pushDynamicScreen(
context,
screen: HomeModalScreen(),
withNavBar: true,
);
一些有用的提示
- 跳转到给定标签的导航图中的任意屏幕:
Navigator.of(context).popUntil((route) {
return route.settings.name == "ScreenToPopBackTo";
});
- 跳转回给定标签的第一个屏幕:
Navigator.of(context).popUntil(ModalRoute.withName("/"));
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(
builder: (BuildContext context) {
return FirstScreen();
},
),
(_) => false,
);
- 若要在导航栏顶部推送底部视图,请使用
showModalBottomScreen
并将其属性useRootNavigator
设置为 true。有关示例,请参阅示例项目。
自定义导航栏样式
如果你想为导航栏自定义样式,请遵循以下步骤:
- 声明你的自定义 widget。请注意,你需要自己处理
onSelectedItem
函数和整数selectedIndex
以维护完整功能。同样,请注意你可以定义自己的导航栏项模型,而不是使用提供的PersistentBottomNavBarItem
。以下是更好的理解示例:
class CustomNavBarWidget extends StatelessWidget {
final int selectedIndex;
final List<PersistentBottomNavBarItem> items; // 注意:你可以在这里声明自己的模型,而不仅仅是 `PersistentBottomNavBarItem`。
final ValueChanged<int> onItemSelected;
CustomNavBarWidget({
Key key,
this.selectedIndex,
@required this.items,
this.onItemSelected,
});
Widget _buildItem(PersistentBottomNavBarItem item, bool isSelected) {
return Container(
alignment: Alignment.center,
height: 60.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: IconTheme(
data: IconThemeData(
size: 26.0,
color: isSelected
? (item.activeColorSecondary == null
? item.activeColorPrimary
: item.activeColorSecondary)
: item.inactiveColorPrimary == null
? item.activeColorPrimary
: item.inactiveColorPrimary),
child: item.icon,
),
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: Material(
type: MaterialType.transparency,
child: FittedBox(
child: Text(
item.title,
style: TextStyle(
color: isSelected
? (item.activeColorSecondary == null
? item.activeColorPrimary
: item.activeColorSecondary)
: item.inactiveColorPrimary,
fontWeight: FontWeight.w400,
fontSize: 12.0,
),
),
),
),
)
],
),
);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Container(
width: double.infinity,
height: 60.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items.map((item) {
int index = items.indexOf(item);
return Flexible(
child: GestureDetector(
onTap: () {
this.onItemSelected(index);
},
child: _buildItem(item, selectedIndex == index),
),
);
}).toList(),
),
),
);
}
}
- 在主
PersistentTabView
widget 中,将navBarStyle
属性设置为NavBarStyle.custom
,并将刚刚创建的自定义 widget 传递给customWidget
属性,如下所示:
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return PersistentTabView.custom(
context,
controller: _controller,
itemCount: items.length, // 这在自定义样式的情况下是必需的!传递导航栏项目的数量。
screens: _buildScreens(),
confineInSafeArea: true,
handleAndroidBackButtonPress: true,
onItemSelected: (int) {
setState(() {});
},
customWidget: CustomNavBarWidget( // 你的自定义 widget 在这里
items: _navBarsItems(),
selectedIndex: _controller.index,
onItemSelected: (index) {
setState(() {
_controller.index = index; // 注意:这是关键!不要遗漏。
});
},
),
);
}
}
更多关于Flutter持久化底部导航栏插件persistent_bottom_nav_bar_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter持久化底部导航栏插件persistent_bottom_nav_bar_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 persistent_bottom_nav_bar_2
插件在 Flutter 中实现持久化底部导航栏的示例代码。
首先,确保你的 pubspec.yaml
文件中已经添加了 persistent_bottom_nav_bar_2
依赖:
dependencies:
flutter:
sdk: flutter
persistent_bottom_nav_bar_v2: ^4.0.3 # 请注意版本号,根据实际情况进行调整
然后运行 flutter pub get
来获取依赖。
接下来是一个完整的示例代码,展示了如何使用 persistent_bottom_nav_bar_2
插件:
import 'package:flutter/material.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent-theme.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Persistent Bottom Nav Bar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: PersistentBottomNavBarDemo(),
);
}
}
class PersistentBottomNavBarDemo extends StatefulWidget {
@override
_PersistentBottomNavBarDemoState createState() => _PersistentBottomNavBarDemoState();
}
class _PersistentBottomNavBarDemoState extends State<PersistentBottomNavBarDemo>
with SingleTickerProviderStateMixin {
int _selectedIndex = 0;
final List<PersistentBottomNavBarItem> _navItems = [
PersistentBottomNavBarItem(
icon: Icon(Icons.home),
title: ("Home"),
activeColorPrimary: Colors.blue,
inactiveColorPrimary: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.search),
title: ("Search"),
activeColorPrimary: Colors.red,
inactiveColorPrimary: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.library_books),
title: ("Library"),
activeColorPrimary: Colors.green,
inactiveColorPrimary: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.profile),
title: ("Profile"),
activeColorPrimary: Colors.purple,
inactiveColorPrimary: Colors.grey,
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _selectedIndex,
children: [
HomeScreen(),
SearchScreen(),
LibraryScreen(),
ProfileScreen(),
],
),
bottomNavigationBar: PersistentBottomNavBar(
navBarStyle: NavBarStyle.style12,
items: _navItems,
currentIndex: _selectedIndex,
onItemSelected: (index) {
setState(() {
_selectedIndex = index;
});
},
animationDuration: Duration(milliseconds: 200),
backgroundColor: Colors.white,
persistentBehavior: PersistentBehavior.none,
hideNavigationBarWhenKeyboardShows: true,
elevation: 8.0,
forceIconsUp: false,
),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('Home Screen'),
);
}
}
class SearchScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('Search Screen'),
);
}
}
class LibraryScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('Library Screen'),
);
}
}
class ProfileScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('Profile Screen'),
);
}
}
在这个示例中:
- 我们定义了一个
PersistentBottomNavBarDemo
类,它包含了一个底部导航栏 (PersistentBottomNavBar
) 和一个IndexedStack
,用于显示当前选中的页面。 PersistentBottomNavBarItem
列表包含了四个导航项,每个导航项都有一个图标和标题,以及激活和未激活时的颜色。PersistentBottomNavBar
的onItemSelected
回调用于更新当前选中的索引,并重新构建界面。HomeScreen
、SearchScreen
、LibraryScreen
和ProfileScreen
是四个简单的页面,它们分别显示不同的文本。
这个示例展示了如何使用 persistent_bottom_nav_bar_2
插件创建一个具有持久化功能的底部导航栏。你可以根据需要进一步自定义和扩展这个示例。