infinite_scrollable_tabbar 0.0.1
infinite_scrollable_tabbar: ^0.0.1 copied to clipboard
A fully customizable Flutter tab bar with infinite scrolling capability. Create horizontally scrollable tab bars where tabs repeat seamlessly in both directions.
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.