Infinite Scrollable TabBar
A Flutter package providing a fully customizable tab bar with infinite scrolling capability. Create horizontally scrollable tab bars where tabs repeat seamlessly in both directions, providing a fluid and engaging user experience.
Features
- β¨ Infinite Scrolling: Tabs repeat seamlessly in both directions for unlimited scrolling
 - π― Smart Controller: Custom controller with intelligent index mapping for programmatic navigation
 - π¨ Fully Customizable: Customize styles, indicators, tab builders, and more
 - π Smooth Animations: Built-in support for animated transitions between tabs
 - π± Responsive: Works seamlessly with dynamic tab lists
 - π Easy Integration: Simple API with sensible defaults, works out of the box
 
Installation
Add this to your package's pubspec.yaml file:
dependencies:
  infinite_scrollable_tabbar: ^0.0.1
Then run:
flutter pub get
Usage
Basic Example
import 'package:flutter/material.dart';
import 'package:infinite_scrollable_tabbar/infinite_scrollable_tabbar.dart';
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  late final InfiniteScrollableTabController _controller;
  late final List<TabItem> _tabs;
  @override
  void initState() {
    super.initState();
    _tabs = [
      const TabItem(label: 'Home'),
      const TabItem(label: 'Search'),
      const TabItem(label: 'Profile'),
      const TabItem(label: 'Settings'),
    ];
    _controller = InfiniteScrollableTabController(
      initialIndex: 0,
      tabCount: _tabs.length,
    );
  }
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          InfiniteScrollableTabBar(
            controller: _controller,
            tabs: _tabs,
            onTabTap: (index) {
              setState(() {});
              print('Tapped tab at index: $index');
            },
          ),
          Expanded(
            child: Center(
              child: Text('Selected: ${_tabs[_controller.currentIndex].label}'),
            ),
          ),
        ],
      ),
    );
  }
}
Customized Styling
InfiniteScrollableTabBar(
  controller: _controller,
  tabs: _tabs,
  height: 70,
  tabWidth: 120,
  backgroundColor: Colors.deepPurple[50],
  selectedTabStyle: const TextStyle(
    fontSize: 18,
    fontWeight: FontWeight.bold,
    color: Colors.deepPurple,
  ),
  unselectedTabStyle: TextStyle(
    fontSize: 16,
    color: Colors.grey[600],
  ),
  indicatorBuilder: () => Container(
    width: 80,
    height: 4,
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [Colors.deepPurple, Colors.purpleAccent],
      ),
      borderRadius: BorderRadius.circular(2),
    ),
  ),
  onTabTap: (index) {
    // Handle tab tap
  },
)
Tabs with Icons
final tabs = [
  TabItem(
    label: 'Home',
    icon: const Icon(Icons.home),
  ),
  TabItem(
    label: 'Search',
    icon: const Icon(Icons.search),
  ),
  TabItem(
    label: 'Profile',
    icon: const Icon(Icons.person),
  ),
];
InfiniteScrollableTabBar(
  controller: _controller,
  tabs: tabs,
  height: 90,
  indicatorPosition: IndicatorPosition.top,
  onTabTap: (index) {
    // Handle tap
  },
)
Programmatic Scrolling
The controller provides intelligent scrolling methods:
// Animate to a specific tab index using the shortest path
// Automatically determines whether to scroll forward or backward
_controller.animateToIndex(
  2,
  duration: const Duration(milliseconds: 500),
  curve: Curves.easeInOut,
);
// Jump to a tab instantly without animation
_controller.jumpToIndex(3);
// Get the current selected index
final currentIndex = _controller.currentIndex;
Tap vs Programmatic Scrolling:
- Tap Behavior: When you tap a visible tab, it scrolls directly to that specific instance (natural feel)
 - Programmatic Behavior: 
animateToIndex()uses shortest-path logic, choosing the most efficient direction 
This means tapping Tab 3 when you're at Tab 5 will scroll to the visible Tab 3 you tapped, while calling animateToIndex(2) programmatically will choose the shortest circular path.
Custom Tab Builder
InfiniteScrollableTabBar(
  controller: _controller,
  tabs: _tabs,
  tabBuilder: (tab, isSelected) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: isSelected ? Colors.blue : Colors.transparent,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        tab.label,
        style: TextStyle(
          color: isSelected ? Colors.white : Colors.black,
          fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
        ),
      ),
    );
  },
)
API Reference
InfiniteScrollableTabBar
The main widget for displaying the infinite scrollable tab bar.
Properties
| Property | Type | Default | Description | 
|---|---|---|---|
controller | 
InfiniteScrollableTabController | 
required | Controller for managing state and scrolling | 
tabs | 
List<TabItem> | 
required | List of tab items to display | 
onTabTap | 
ValueChanged<int>? | 
null | Callback when a tab is tapped | 
height | 
double | 
56.0 | Height of the tab bar | 
tabWidth | 
double | 
100.0 | Width of each tab | 
tabPadding | 
EdgeInsets | 
(16, 8) | Padding for tab content | 
selectedTabStyle | 
TextStyle? | 
null | Text style for selected tab | 
unselectedTabStyle | 
TextStyle? | 
null | Text style for unselected tabs | 
tabBuilder | 
Function? | 
null | Custom builder for tab content | 
indicatorBuilder | 
Function? | 
null | Custom builder for indicator | 
indicatorPosition | 
IndicatorPosition | 
bottom | Position of indicator (top/bottom) | 
backgroundColor | 
Color? | 
null | Background color of tab bar | 
showIndicator | 
bool | 
true | Whether to show the indicator | 
physics | 
ScrollPhysics? | 
null | Physics for scroll behavior | 
InfiniteScrollableTabController
Controller for managing the tab bar state and programmatic scrolling.
Constructor Parameters
| Parameter | Type | Default | Description | 
|---|---|---|---|
tabCount | 
int | 
required | Total number of unique tabs | 
initialIndex | 
int | 
0 | Initial selected tab index | 
repetitions | 
int | 
1000 | Number of repetitions for infinite scrolling | 
Methods
animateToIndex(int index, {Duration?, Curve?, double?}): Smoothly animate to a tab using shortest pathanimateToVirtualIndex(int virtualIndex, {Duration?, Curve?, double?}): Animate to a specific tab instancejumpToIndex(int index, {double?}): Instantly jump to a tab using shortest pathdispose(): Clean up resources
Properties
currentIndex: Get the current selected tab indexscrollController: Access the underlying scroll controller
TabItem
Data model representing a single tab.
Constructor Parameters
| Parameter | Type | Required | Description | 
|---|---|---|---|
label | 
String | 
yes | Text label for the tab | 
icon | 
Widget? | 
no | Optional icon widget | 
badge | 
Widget? | 
no | Optional badge widget | 
Examples
Check out the example directory for comprehensive demos including:
- Basic usage with text tabs
 - Custom styled tabs
 - Tabs with icons
 - Programmatic scrolling
 - Dynamic tab management
 
To run the example:
cd example
flutter run
How It Works
The infinite scrolling effect is achieved by:
- Virtual Repetition: The tabs are repeated multiple times (default: 1000) in the underlying scroll view
 - Middle Positioning: The scroll view starts in the middle of the virtual list
 - Smart Indexing: The controller maps real indices (0 to n-1) to virtual positions in the list
 - Seamless Scrolling: Users can scroll in either direction indefinitely
 
This approach provides a true infinite scrolling experience while maintaining excellent performance.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development
- Fork the repository
 - Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
 
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
If you find this package useful, please consider:
- β Starring the repository
 - π Reporting bugs or requesting features via GitHub Issues
 - π Contributing to the documentation
 
Acknowledgments
Built with β€οΈ using Flutter.
Libraries
- infinite_scrollable_tabbar
 - A Flutter package providing a fully customizable tab bar with infinite scrolling capability.