This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
TabBar
TabBar is a tab bar: a strip of buttons (tab strip) + a horizontally scrollable content panel with per-page snap (via PageScrollEngine). Tapping a tab scrolls the content to the corresponding page; dragging the content switches the active tab. An animated indicator follows the active tab.
The aesthetics (indicator, tabs at the top or bottom, colors) come from the active Skin (TabBarStyle). Each tab is described by a TabBar.Tab (text, icon or both).
🟡 · Package:
dev.crossfly.ui· Extends:Component· Style:TabBarStyle(viagetSkin().tabBar())
When to use
- Navigation between 2–5 sections of a screen (Home / Search / Profile).
- Paginated content with a swipe gesture between pages + synchronized tabs.
When NOT to use
- Many sections that don’t fit (the strip scrolls, but becomes less legible) → consider a different navigation.
Appearance
Equal-width tab strip (1/n); if they don’t fit, the strip becomes horizontally scrollable and the tabs switch to automatic width. The indicator slides under (or over, if tabsAtBottom) the active tab. The content panel shows one page at a time with snap.
Complete example (copy, paste and run)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
// One content view per tab (the count MUST match the number of tabs).
Label resumo = new Label("Conteúdo do Resumo");
Label detalhes = new Label("Conteúdo dos Detalhes");
Label historico = new Label("Conteúdo do Histórico");
TabBar tabs = new TabBar(
new TabBar.Tab("Resumo"),
new TabBar.Tab("Detalhes"),
new TabBar.Tab("Histórico"));
tabs.setContent(resumo, detalhes, historico);
tabs.onTabChanged(i -> System.out.println("aba " + i));
add(LAY_FILL, tabs); // the TabBar absorbs the remaining height
}
}
The snippets below show only the core (what goes inside
onShow()). To run them, place them in theMainWindowskeleton above.
Basic usage
TabBar tabs = new TabBar(
new TabBar.Tab("Home", new MaterialIcon("")),
new TabBar.Tab("Buscar", new MaterialIcon("")),
new TabBar.Tab("Perfil", new MaterialIcon("")));
tabs.setContent(homeView, searchView, profileView);
tabs.onTabChanged(i -> System.out.println("aba " + i));
add(LAY_FILL, tabs);
Constructors
| Constructor | Description |
|---|---|
TabBar(Tab... tabs) |
Creates the bar with the tabs (activeIndex = 0) |
TabBar.Tab (tab descriptor)
| Constructor | Result |
|---|---|
Tab(String text) |
Text only (TextPos.NONE) |
Tab(Icon icon) |
Icon only (TextPos.NONE) |
Tab(String text, Icon icon) |
Text + icon (TextPos.TEXT_AT_BOTTOM) |
Tab(String text, Icon icon, TextPos textPos) |
Text + icon with a custom position |
Properties and customization
| Property / method | Type | What it does |
|---|---|---|
setContent(Component...) |
TabBar |
Content per tab (the count must match the tabs, otherwise IllegalArgumentException) |
setActiveTab(int) |
TabBar |
Activates a tab programmatically (with animation/scroll); no-op if invalid or already active |
getActiveIndex() |
int |
Index of the active tab |
getTabs() |
Tab[] |
The tab descriptors |
getStrip() / getTabButtons() / getContentPanel() |
— | Access to internals |
getIndicatorX() / getIndicatorW() |
float |
Current position/width of the indicator (for painting in Design) |
Callbacks and events
| Callback | When it fires |
|---|---|
onTabChanged(TabChangedListener) |
On tab change, by tap, swipe or setActiveTab(...) |
TabChangedListener is functional: void onTabChanged(int index).
States
- Active — only one tab at a time; the indicator animates to it (duration
TabBarStyle.switchDuration). - User swipe — the indicator interpolates continuously between neighboring tabs; when crossing to another page,
activeIndexswitches andonTabChangedfires. - Programmatic —
setActiveTab/tap lock the synchronization until the scroll animation reaches the target.
Text-only tabs
TabBar tabs = new TabBar(
new TabBar.Tab("Resumo"),
new TabBar.Tab("Detalhes"),
new TabBar.Tab("Histórico"));
tabs.setContent(resumoView, detalhesView, historicoView);
add(LAY_FILL, tabs);
Programmatic tab switch
TabBar tabs = new TabBar(new TabBar.Tab("A"), new TabBar.Tab("B"), new TabBar.Tab("C"));
tabs.setContent(viewA, viewB, viewC);
add(LAY_FILL, tabs);
// ... later:
tabs.setActiveTab(2); // animates to tab C
Best practices
- The count of
setContent(...)must match the number of tabs. - For tabs at the bottom (iOS style), use a
SkinwhoseTabBarStyle.tabsAtBottom = true— the layout and the indicator adjust themselves. - Don’t force a fixed width on the tabs: if they don’t fit, the strip scrolls on its own.
Common mistakes
setContentwith the wrong count →IllegalArgumentException. Pass exactly one view per tab.- Expecting
setActiveTabto fireonTabChangedfor the already-active index — it is a no-op whenindex == activeIndex.