搜索插件、代码仓与 APP 分类

dynamic_tabbar 封面
插件详情v1.0.9

dynamic_tabbar

Flutter 包,以最简单的方式处理动态标签(TabBar 和 TabBarView)。

AndroidiOSWeb
近 30 天下载
3600
喜欢数
125
Pub 分数
150

安装插件

flutter pub add dynamic_tabbar

插件介绍

基于插件公开信息、社区数据与项目使用情况整理的选型参考。

一个 Flutter 包,可简化使用 TabBar 和 TabBarView 创建和管理动态标签页的过程。它允许开发者在运行时轻松添加、删除或更新标签页,而无需复杂的状态管理。该包可无缝处理标签页导航、视图切换和状态保留,非常适合需要灵活标签布局的应用程序。设计以简单为核心,减少样板代码并提升开发效率。兼容 Android、iOS 和 Web 平台。

适合场景

  • 构建动态仪表板界面
  • 创建可自定义的选项卡导航
  • 实现用户驱动的标签页添加/删除
  • 开发多部分内容视图
  • 支持实时标签更新

主要特点

  • 运行时选项卡操作
  • 自动状态保留
  • 最小化样板代码
  • 跨平台支持(Android、iOS、Web)
  • 用于添加/删除选项卡的简单 API

适合对象

  • 寻求简单标签页管理的开发者
  • 标签数量可变的应用程序
  • 需要响应式标签页的动态UI
  • 初学者学习Flutter标签模式
  • 需要轻量级标签解决方案的项目

使用建议

  • 超出基本标签样式的有限自定义
  • 无内置的滑动手势支持
  • 需要手动处理与选项卡相关的逻辑
  • 不太适合高度复杂的标签层级
  • 依赖外部状态管理以支持高级用例

原始 README

以下为关联源码仓库的 README 原文快照,最新内容请访问源码仓库。

dynamic_tabbar

Dynamic TabBar

A Flutter package that simplifies the implementation of dynamic TabBar in your application.

With DynamicTabBarWidget, users can effortlessly manage and navigate through a list of Tabs. The widget is designed to auto-update as Tabs are added or removed, providing a seamless and dynamic user experience.

🚀 Demo: Dynamic Tabbar

📱 Screenshots

dynamic_tabbar Demo 1 dynamic_tabbar Demo 2 dynamic_tabbar Demo 4 dynamic_tabbar Web Demo

🛠 Installation

  1. Add dependency to pubspec.yaml file:
    Get the latest version from the 'Installing' tab on pub.dev
dependencies:
  dynamic_tabbar: ^latest_version
  1. Import the package
import 'package:dynamic_tabbar/dynamic_tabbar.dart';
  1. Adding DynamicTabBarWidget

With required parameters

 DynamicTabBarWidget(
    dynamicTabs: tabs,
);

With optional parameters

 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

  • Dynamic Tab Management: Users can push or pop items in the List<TabData> tabs array, and the DynamicTabBarWidget will auto-update accordingly.

  • Tab Navigation: Implement the onTabChanged callback to handle tab change events.

  • Customization Options: Customize the appearance and behavior of the DynamicTabBarWidget using parameters like backIcon, nextIcon, showBackIcon, and showNextIcon.

  • Tab Position : Specify the position to which cursor moves to after adding new Tab using the onAddTabMoveTo property.

🧰 Parameters
  • dynamicTabs: List of TabData objects representing the dynamic tabs.

  • isScrollable: Set to true to enable scrollable tabs.

  • onTabChanged: Callback function triggered when a tab is changed.

  • onAddTabMoveTo: Enum value (MoveToTab.idol, MoveToTab.last) specifying where a tab navigator should move when Tab is added.

  • backIcon: Custom icon for the "Back" button, If isScrollable is false, this property is ignored.

  • nextIcon: Custom icon for the "Next" button.

  • showBackIcon: Boolean to show or hide the Back icon button, If isScrollable is false, this property is ignored.

  • showNextIcon: Boolean to show or hide the Next icon button, If isScrollable is false, this property is ignored.

  • leading: Custom leading Widget if needed.

  • trailing: Custom trailing Widget if needed.

  • TabBar default properties...

  • and TabBarView default properties...

📚 How to use

isScrollable
isScrollable: false isScrollable: true
isScrollable.false isScrollable.true
showBackIcon

If isScrollable is false, this property is ignored.

showBackIcon: false showBackIcon: true
isScrollable.true isScrollable.true
showNextIcon

If isScrollable is false, this property is ignored.

showNextIcon: false showNextIcon: true
isScrollable.true isScrollable.true
backIcon

We can use custom Icon for back button, If isScrollable is false, this property is ignored.

backIcon: Icon() backIcon: null
Icon(Icons.keyboard_double_arrow_left) Default back icon will be used
isScrollable.true isScrollable.true
nextIcon

We can use custom Icon for next button, If isScrollable is false, this property is ignored.

nextIcon: Icon() nextIcon: null
Icon(Icons.keyboard_double_arrow_right) Default back icon will be used
nextIcon_custom default_icons

💻 Example

Check out the example app in the example directory for a complete example with additional parameters.

import 'package:flutter/material.dart';
import 'package:dynamic_tabbar/dynamic_tabbar.dart';


class DynamicTabExample extends StatefulWidget {
  const DynamicTabExample({super.key});
  @override
  State<DynamicTabExample> createState() => _DynamicTabExampleState();
}

class _DynamicTabExampleState extends State<DynamicTabExample> {
  bool isScrollable = false;
  bool showNextIcon = true;
  bool showBackIcon = true;

  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
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Example for Dynamic Tab'),
      ),
      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),
                ElevatedButton(
                  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;
                        });
                      },
                    ),
                  ],
                ),
              ],
            ),
          ),
          Expanded(
            child: DynamicTabBarWidget(
              dynamicTabs: tabs,
              isScrollable: isScrollable,
              onTabControllerUpdated: (controller) {},
              onTabChanged: (index) {},
              onAddTabMoveTo: MoveToTab.last,
              showBackIcon: showBackIcon,
              showNextIcon: showNextIcon,
            ),
          ),
        ],
      ),
    );
  }

  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);
    });
  }
}

📝Contribution

Of course the project is open source, and you can contribute to it repository link

  • If you found a bug, open an issue.

  • If you have a feature request, open an issue.

  • If you want to contribute, submit a pull request.

💳 License

This project is LICENSED under the MIT License. Use it freely, but let's play nice and give credit where it's due!

🎉 Conclusion

I will be happy to answer any questions that you may have on this approach,
If you liked this package, don't forget to show some ❤️ by smashing the ⭐.

所属分类

源码仓库

使用此插件的项目

暂无相关数据。