Flutter widget inspired by the classic Desktop-style tab component. Supports customizable themes.
The TabbedViewTheme.classic() method builds the default theme.
List<TabData> tabs = [];
for (var i = 1; i < 7; i++) {
Widget tabContent = Center(child: Text('Content $i'));
tabs.add(TabData(text: 'Tab $i', content: tabContent));
}
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
It allows creating the contents of the tab dynamically during the selection event.
var tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedView tabbedView = TabbedView(
controller: TabbedViewController(tabs),
contentBuilder: (BuildContext context, int tabIndex) {
int i = tabIndex + 1;
return Center(child: Text('Content $i'));
});
var tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedView tabbedView = TabbedView(
controller: TabbedViewController(tabs),
closeButtonTooltip: 'Click here to close the tab');
TabData tab = TabData(text: 'Tab', buttons: [
TabButton(
icon: IconProvider.data(Icons.star),
onPressed: () => showSnackBar(context: context, msg: 'Hello!'))
]);
TabbedView tabbedView = TabbedView(controller: TabbedViewController([tab]));
TabData tab = TabData(text: 'Tab', buttons: [
TabButton(
icon: IconProvider.path(_path),
onPressed: () => showSnackBar(context: context, msg: 'Hello!'))
]);
TabbedView tabbedView = TabbedView(controller: TabbedViewController([tab]));
Path _path(Size size) {
Path path = Path();
path.moveTo(size.width * 0.1, size.height * 0.1);
path.lineTo(size.width * 0.9, size.height * 0.1);
path.lineTo(size.width * 0.9, size.height * 0.9);
path.lineTo(size.width * 0.1, size.height * 0.9);
path.close();
return path;
}
var tabs = [
TabData(text: 'Tab', buttons: [
TabButton(
icon: IconProvider.data(Icons.star),
color: Colors.green,
onPressed: () => showSnackBar(context: context, msg: 'Hello!'))
])
];
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
var tabs = [
TabData(text: 'Tab', buttons: [
TabButton(
icon: IconProvider.path(TabbedViewIcons.menu),
menuBuilder: (context) {
return [
TabbedViewMenuItem(
text: 'Menu item 1',
onSelection: () =>
showSnackBar(context: context, msg: 'menu item 1')),
TabbedViewMenuItem(
text: 'Menu item 2',
onSelection: () =>
showSnackBar(context: context, msg: 'menu item 2'))
];
})
])
];
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
var tabs = [
TabData(text: 'Tab'),
TabData(text: 'Non-closable tab', closable: false)
];
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
bool _tabCloseInterceptor(int tabIndex) {
if (tabIndex == 0) {
print('The tab $tabIndex is busy and cannot be closed.');
return false;
}
return true;
}
List<TabData> tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedView tabbedView = TabbedView(
controller: TabbedViewController(tabs),
tabCloseInterceptor: _tabCloseInterceptor);
List<TabData> tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedView tabbedView = TabbedView(
controller: TabbedViewController(tabs),
onTabClose: (index, tabData) {
print('$index: ' + tabData.text);
});
_onTabSelection(int? newTabIndex) {
print('The new selected tab is $newTabIndex.');
}
List<TabData> tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedView tabbedView = TabbedView(
controller: TabbedViewController(tabs),
onTabSelection: _onTabSelection);
List<TabData> tabs = [
TabData(
text: 'Tab 1',
leading: (context, status) => Icon(Icons.star, size: 16)),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
List<TabData> tabs = [];
for (var i = 1; i < 7; i++) {
Widget tabContent = Center(child: Text('Content $i'));
tabs.add(TabData(text: 'Tab $i', content: tabContent));
}
_controller = TabbedViewController(tabs);
TabbedView tabbedView = TabbedView(
controller: _controller,
onDraggableBuild: (int tabIndex, TabData tabData) {
return DraggableConfig(
feedback: Container(
child: Text(tabData.text),
padding: EdgeInsets.all(4),
decoration: BoxDecoration(border: Border.all())));
});
DragTarget<TabData> dragTarget = DragTarget(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
padding: EdgeInsets.all(8),
color: Colors.yellow[100],
child: Center(
child: ListTile(
title: Text('Drop here'),
subtitle: Text('Last dropped tab: ${_acceptedData ?? ''}'))),
);
},
onAccept: (TabData data) {
setState(() {
_acceptedData = data.text;
});
},
);
The keepAlive
parameter indicates whether to keep the tab content widget in memory even if it is not visible. Indicated to prevent loss of state due to tree change by tab selection. If enabled, the Widget will continue to be instantiated in the tree but will remain invisible. The default value is FALSE
.
TabbedViewController controller = TabbedViewController([]);
TabbedView tabbedView = TabbedView(
controller: controller,
tabsAreaButtonsBuilder: (context, tabsCount) {
List<TabButton> buttons = [];
buttons.add(TabButton(
icon: IconProvider.data(Icons.add),
onPressed: () {
int millisecond = DateTime.now().millisecondsSinceEpoch;
controller.addTab(TabData(text: '$millisecond'));
}));
if (tabsCount > 0) {
buttons.add(TabButton(
icon: IconProvider.data(Icons.delete),
onPressed: () {
if (controller.selectedIndex != null) {
controller.removeTab(controller.selectedIndex!);
}
}));
}
return buttons;
});
var tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
];
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
TabbedViewThemeData themeData = TabbedViewThemeData.classic()
..tab.textStyle = TextStyle(fontSize: 20, color: Colors.blue);
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
var tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
];
TabbedView tabbedView = TabbedView(controller: TabbedViewController(tabs));
TabbedViewThemeData themeData = TabbedViewThemeData.classic();
themeData.tab
..textStyle = TextStyle(fontSize: 20)
..verticalAlignment = VerticalAlignment.top;
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewThemeData themeData = TabbedViewThemeData.classic();
themeData.tabsArea.color = Colors.green[100];
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewThemeData themeData = TabbedViewThemeData.classic();
themeData.tabsArea
..initialGap = 20
..middleGap = 5
..minimalFinalGap = 5;
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewThemeData themeData = TabbedViewThemeData.classic()
..tabsArea.menuIcon =
IconProvider.data(Icons.arrow_drop_down_circle_outlined);
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewThemeData themeData = TabbedViewThemeData.classic()
..menu.maxWidth = 100;
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
var tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3'),
TabData(
text: 'The name of the tab is so long that it doesn'
't fit on the menu')
];
TabbedViewController controller = TabbedViewController(tabs);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewThemeData themeData = TabbedViewThemeData.classic()
..menu.ellipsisOverflowText = true;
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme =
TabbedViewTheme(child: tabbedView, data: TabbedViewThemeData.classic());
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme = TabbedViewTheme(
child: tabbedView,
data: TabbedViewThemeData.classic(colorSet: Colors.green));
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme =
TabbedViewTheme(child: tabbedView, data: TabbedViewThemeData.dark());
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme = TabbedViewTheme(
child: tabbedView,
data: TabbedViewThemeData.dark(colorSet: Colors.indigo));
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme =
TabbedViewTheme(child: tabbedView, data: TabbedViewThemeData.mobile());
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme = TabbedViewTheme(
child: tabbedView,
data: TabbedViewThemeData.mobile(colorSet: Colors.blueGrey));
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme = TabbedViewTheme(
child: tabbedView,
data: TabbedViewThemeData.mobile(accentColor: Colors.green[700]!));
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme = TabbedViewTheme(
child: tabbedView, data: TabbedViewThemeData.minimalist());
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewTheme theme = TabbedViewTheme(
child: tabbedView,
data: TabbedViewThemeData.minimalist(colorSet: Colors.blue));
It is possible to create an entire theme from scratch.
var tabs = [
TabData(text: 'Tab 1'),
TabData(text: 'Tab 2'),
TabData(text: 'Tab 3')
];
TabbedViewController controller = TabbedViewController(tabs);
TabbedView tabbedView = TabbedView(controller: controller);
TabbedViewThemeData themeData = TabbedViewThemeData();
themeData.tabsArea
..border = Border(bottom: BorderSide(color: Colors.green[700]!, width: 3))
..middleGap = 6;
Radius radius = Radius.circular(10.0);
BorderRadiusGeometry? borderRadius =
BorderRadius.only(topLeft: radius, topRight: radius);
themeData.tab
..padding = EdgeInsets.fromLTRB(10, 4, 10, 4)
..buttonsOffset = 8
..decoration = BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.green[100],
borderRadius: borderRadius)
..selectedStatus.decoration =
BoxDecoration(color: Colors.green[200], borderRadius: borderRadius)
..highlightedStatus.decoration =
BoxDecoration(color: Colors.green[50], borderRadius: borderRadius);
TabbedViewTheme theme = TabbedViewTheme(child: tabbedView, data: themeData);
bc1qhqy84y45gya58gtfkvrvass38k4mcyqnav803h
0x9eB815FD4c88A53322304143A9Aa8733D3369985
7vp45LoQXtLYFXXKx8wQGnzYmhcnKo1TmfqUgMX45Ad8