alihaider78222 / dynamic_tabbar

Flutter package for creating dynamic tabs (TabBar and TabBarView).
https://pub.dev/packages/dynamic_tabbar
MIT License
14 stars 11 forks source link
dart dart-package dynamic dynamic-tab dynamic-tabbar dynamic-tabs flutter flutter-package tabbar tabbarcontroller tabbarview tabs tabs-component tabs-management tabs-switching tabs-widget

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

๐Ÿงฐ Parameters

๐Ÿ“š 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

๐Ÿ’ณ 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 โญ.