Flutter动态底部导航栏插件dynamic_tabbar的使用
Flutter动态底部导航栏插件dynamic_tabbar的使用
动态TabBar
Dynamic TabBar
是一个Flutter包,简化了在应用中实现动态TabBar的过程。通过DynamicTabBarWidget
,用户可以轻松管理并浏览一系列的Tabs
。该组件设计为当Tabs
被添加或移除时自动更新,提供无缝且动态的用户体验。
🚀 在线演示
📱 Screenshots
Demo 1 | Demo 2 | Demo 4 | Web Demo |
---|---|---|---|
🛠 Installation
- 在
pubspec.yaml
文件中添加依赖:
dependencies:
dynamic_tabbar: ^latest_version
请从pub.dev获取最新版本。 2. 导入包:
import 'package:dynamic_tabbar/dynamic_tabbar.dart';
- 使用
DynamicTabBarWidget
,例如:
必填参数
DynamicTabBarWidget(
dynamicTabs: tabs,
);
可选参数
DynamicTabBarWidget(
dynamicTabs: tabs,
isScrollable: isScrollable,
onTabControllerUpdated: (controller) {},
onTabChanged: (index) {},
onAddTabMoveTo: MoveToTab.last,
onAddTabMoveToIndex : null,
backIcon: Icon(Icons.arrow_back),
nextIcon: Icon(Icons.arrow_forward),
showBackIcon: showBackIcon,
showNextIcon: showNextIcon,
leading : leadingWidget,
trailing : trailingWidget,
// Default Tab properties can also be updated
padding: padding,
indicatorColor: indicatorColor,
automaticIndicatorColorAdjustment: automaticIndicatorColorAdjustment,
indicatorWeight: indicatorWeight,
indicatorPadding: indicatorPadding,
indicator: indicator,
indicatorSize: indicatorSize,
dividerColor: dividerColor,
dividerHeight: dividerHeight,
labelColor: labelColor,
labelStyle: labelStyle,
labelPadding: labelPadding,
unselectedLabelColor: unselectedLabelColor,
unselectedLabelStyle: unselectedLabelStyle,
dragStartBehavior: dragStartBehavior,
overlayColor: overlayColor,
mouseCursor: mouseCursor,
enableFeedback: enableFeedback,
onTap: onTap,
physics: physics,
splashFactory: splashFactory,
splashBorderRadius: splashBorderRadius,
tabAlignment: tabAlignment,
// Default TabBarView properties can also be updated
physicsTabBarView: physicsTabBarView,
dragStartBehaviorTabBarView: physicsTabBarView,
viewportFractionTabBarView: viewportFractionTabBarView,
clipBehaviorTabBarView: clipBehaviorTabBarView,
);
🌟 Features
- 动态标签管理:用户可以在
List<TabData> tabs
数组中推送或弹出项目,DynamicTabBarWidget
将根据情况自动更新。 - 标签导航:通过实现
onTabChanged
回调来处理标签切换事件。 - 自定义选项:使用如
backIcon, nextIcon, showBackIcon, and showNextIcon
等参数自定义DynamicTabBarWidget
的外观和行为。 - 标签位置:使用
onAddTabMoveTo
属性指定添加新标签后光标应移动的位置。
🧰 Parameters
dynamicTabs
: 表示动态标签的TabData
对象列表。isScrollable
: 设置为true以启用可滚动标签。onTabChanged
: 标签更改时触发的回调函数。onAddTabMoveTo
: 枚举值(MoveToTab.idol
,MoveToTab.last
)指定添加标签后标签导航器应移动到的位置。backIcon
: 自定义“返回”按钮图标,如果isScrollable
为false,则忽略此属性。nextIcon
: 自定义“下一个”按钮图标。showBackIcon
: 显示或隐藏“返回”图标按钮的布尔值,如果isScrollable
为false,则忽略此属性。showNextIcon
: 显示或隐藏“下一个”图标按钮的布尔值,如果isScrollable
为false,则忽略此属性。leading
: 如有需要的自定义leading Widget
。trailing
: 如有需要的自定义trailing Widget
。
📚 How to use
isScrollable
isScrollable: false |
isScrollable: true |
---|---|
showBackIcon
如果isScrollable
为false,则忽略此属性。
showBackIcon: false |
showBackIcon: true |
---|---|
showNextIcon
如果isScrollable
为false,则忽略此属性。
showNextIcon: false |
showNextIcon: true |
---|---|
backIcon
如果isScrollable
为false,则忽略此属性。
backIcon: Icon() |
backIcon: null |
---|---|
Icon(Icons.keyboard_double_arrow_left) |
默认返回图标将被使用 |
nextIcon
如果isScrollable
为false,则忽略此属性。
nextIcon: Icon() |
nextIcon: null |
---|---|
Icon(Icons.keyboard_double_arrow_right) |
默认返回图标将被使用 |
💻 Example
以下是dynamic_tabbar
插件的一个完整示例,包括如何添加和移除标签、控制是否可滚动以及显示或隐藏前后图标。
import 'package:flutter/material.dart';
import 'package:dynamic_tabbar/dynamic_tabbar.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dynamic TabBar Demo',
theme: ThemeData(
useMaterial3: true,
),
home: const MyHomePage(title: 'Example for Dynamic TabBar'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isScrollable = false;
bool showNextIcon = true;
bool showBackIcon = true;
// Leading icon
Widget? leading;
// Trailing icon
Widget? trailing;
// Sample data for tabs
List<TabData> tabs = [
TabData(
index: 1,
title: const Tab(
child: Text('Tab 1'),
),
content: const Center(child: Text('Content for Tab 1')),
),
TabData(
index: 2,
title: const Tab(
child: Text('Tab 2'),
),
content: const Center(child: Text('Content for Tab 2')),
),
// Add more tabs as needed
];
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.center,
children: [
ElevatedButton(
onPressed: addTab,
child: const Text('Add Tab'),
),
const SizedBox(width: 12),
OutlinedButton(
onPressed: () => removeTab(tabs.length - 1),
child: const Text('Remove Last Tab'),
),
const SizedBox(width: 16),
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('isScrollable'),
Switch.adaptive(
value: isScrollable,
onChanged: (bool val) {
setState(() {
isScrollable = !isScrollable;
});
},
),
],
),
const SizedBox(width: 16),
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('showBackIcon'),
Switch.adaptive(
value: showBackIcon,
onChanged: (bool val) {
setState(() {
showBackIcon = !showBackIcon;
});
},
),
],
),
const SizedBox(width: 16),
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Text('showNextIcon'),
Switch.adaptive(
value: showNextIcon,
onChanged: (bool val) {
setState(() {
showNextIcon = !showNextIcon;
});
},
),
],
),
const SizedBox(width: 22),
ElevatedButton(
onPressed: addLeadingWidget,
child: const Text('Add Leading Widget'),
),
const SizedBox(width: 12),
OutlinedButton(
onPressed: removeLeadingWidget,
child: const Text('remove Leading Widget'),
),
const SizedBox(width: 22, height: 44),
ElevatedButton(
onPressed: addTrailingWidget,
child: const Text('Add Trailing Widget'),
),
const SizedBox(width: 12),
OutlinedButton(
onPressed: removeTrailingWidget,
child: const Text('remove Trailing Widget'),
),
const SizedBox(width: 12),
],
),
),
Expanded(
child: DynamicTabBarWidget(
dynamicTabs: tabs,
// optional properties :-----------------------------
isScrollable: isScrollable,
onTabControllerUpdated: (controller) {
debugPrint("onTabControllerUpdated");
},
onTabChanged: (index) {
debugPrint("Tab changed: $index");
},
onAddTabMoveTo: MoveToTab.last,
// onAddTabMoveToIndex: tabs.length - 1, // Random().nextInt(tabs.length);
// backIcon: Icon(Icons.keyboard_double_arrow_left),
// nextIcon: Icon(Icons.keyboard_double_arrow_right),
showBackIcon: showBackIcon,
showNextIcon: showNextIcon,
leading: leading,
trailing: trailing,
),
),
],
),
);
}
void addTab() {
setState(() {
var tabNumber = tabs.length + 1;
tabs.add(
TabData(
index: tabNumber,
title: Tab(
child: Text('Tab $tabNumber'),
),
content: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Dynamic Tab $tabNumber'),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => removeTab(tabNumber - 1),
child: const Text('Remove this Tab'),
),
],
),
),
);
});
}
void removeTab(int id) {
setState(() {
tabs.removeAt(id);
});
}
void addLeadingWidget() {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'Adding Icon button Widget \nYou can add any customized widget)'),
));
setState(() {
leading = Tooltip(
message: 'Add your desired Leading widget here',
child: IconButton(
onPressed: () {},
icon: const Icon(Icons.more_horiz_rounded),
),
);
});
}
void removeLeadingWidget() {
setState(() {
leading = null;
});
}
void addTrailingWidget() {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'Adding Icon button Widget \nYou can add any customized widget)'),
));
setState(() {
trailing = Tooltip(
message: 'Add your desired Trailing widget here',
child: IconButton(
onPressed: () {},
icon: const Icon(Icons.more_horiz_rounded),
),
);
});
}
void removeTrailingWidget() {
setState(() {
trailing = null;
});
}
}
✏️ Contribution
该项目是开源的,您可以通过访问仓库链接进行贡献。
- 如果您发现了bug,请提交问题。
- 如果您有功能请求,请提交问题。
- 如果您想要贡献,请提交拉取请求。
💳 License
本项目遵循MIT许可证,您可以自由使用,但请给予应有的信用!
🎉 Conclusion
如果您对这种方法有任何疑问,我很乐意为您解答。如果您喜欢这个包,请不要忘记点击⭐支持我们!❤️
更多关于Flutter动态底部导航栏插件dynamic_tabbar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter动态底部导航栏插件dynamic_tabbar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用dynamic_tabbar
插件来实现动态底部导航栏的示例代码。dynamic_tabbar
是一个用于在Flutter应用中实现动态底部导航栏的插件,允许你根据应用状态动态添加、删除或更改导航项。
首先,确保你的pubspec.yaml
文件中已经添加了dynamic_tabbar
依赖:
dependencies:
flutter:
sdk: flutter
dynamic_tabbar: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:dynamic_tabbar/dynamic_tabbar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dynamic TabBar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DynamicTabBarScaffold(
appBar: AppBar(
title: Text('Dynamic TabBar Example'),
),
initController: _initDynamicTabBarController(),
builder: (context, controller) {
return TabBarView(
controller: controller.tabController,
children: [
Center(child: Text('Home Page')),
Center(child: Text('Search Page')),
Center(child: Text('Profile Page')),
// 可以根据需要动态添加更多页面
],
);
},
),
);
}
// 初始化DynamicTabBarController
DynamicTabBarController _initDynamicTabBarController() {
return DynamicTabBarController(
tabList: [
DynamicTabData(
title: 'Home',
icon: Icons.home,
isSelected: true,
),
DynamicTabData(
title: 'Search',
icon: Icons.search,
),
DynamicTabData(
title: 'Profile',
icon: Icons.person,
),
],
onTabItemClick: (index, data) {
// 处理点击事件
print('Clicked on tab: $index');
},
onAddTab: (tabs) {
// 添加新标签的逻辑
setState(() {
tabs.add(
DynamicTabData(
title: 'New Tab',
icon: Icons.add,
),
);
});
},
onRemoveTab: (tabs, index) {
// 移除标签的逻辑
setState(() {
tabs.removeAt(index);
});
},
);
}
}
在这个示例中,我们做了以下几件事:
- 设置
MaterialApp
:创建一个基本的Flutter应用。 - 使用
DynamicTabBarScaffold
:这是一个特殊的Scaffold,它允许我们使用DynamicTabBarController
来管理动态底部导航栏。 - 初始化
DynamicTabBarController
:在_initDynamicTabBarController
方法中,我们设置了初始的导航项,并定义了添加和移除导航项的逻辑。 - 处理
TabBarView
:根据DynamicTabBarController
的状态,显示相应的页面。
注意,这个示例中,添加和移除标签的逻辑使用了setState
来更新UI,但在实际项目中,你可能需要更复杂的逻辑来管理状态,例如使用Provider
、Riverpod
或Bloc
等状态管理库。
此外,dynamic_tabbar
插件可能还有其他配置选项和功能,请参考其官方文档以获取更多信息和高级用法。