This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
How to create tabs (TabBar)
Purpose. Organize content into pages switchable by a tab bar, with an animated indicator and horizontal swipe between pages. Use it for top-level sections (Home / Search / Profile) or to group related content without screen navigation.
APIs used
new TabBar(TabBar.Tab... tabs)— creates the bar from tab descriptors.new TabBar.Tab(String text)— text-only tab.new TabBar.Tab(Icon icon)— icon-only tab.new TabBar.Tab(String text, Icon icon)— tab with text and icon (text below the icon by default).tabBar.setContent(Component... contents)— sets the content of each tab; the count must match the number of tabs (otherwise it throwsIllegalArgumentException).tabBar.onTabChanged(TabBar.TabChangedListener listener)— callbackonTabChanged(int index)called when the active tab changes (by tap or swipe).tabBar.setActiveTab(int index)— switches the tab programmatically (animates the indicator and scrolls the content).tabBar.getActiveIndex()— index of the active tab.
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());
// Text-only tabs (self-contained, without relying on MaterialIcon glyphs)
TabBar tabBar = new TabBar(
new TabBar.Tab("Início"),
new TabBar.Tab("Buscar"),
new TabBar.Tab("Perfil"));
// One content Component per tab, in the SAME order as the tabs
Component telaInicio = new Label("Conteúdo: Início");
Component telaBusca = new Label("Conteúdo: Buscar");
Component telaPerfil = new Label("Conteúdo: Perfil");
tabBar.setContent(
telaInicio,
telaBusca,
telaPerfil);
tabBar.onTabChanged(index ->
{
// e.g.: load data on demand when the tab changes
if (index == 1) carregarBusca();
});
add(LAY_FILL, tabBar);
}
private void carregarBusca()
{
// ... load Search tab data on demand ...
}
}
The snippet below shows just the core. To run it, place it in the
MainWindowskeleton above.
Minimal snippet
TabBar tabBar = new TabBar(
new TabBar.Tab("Início", new MaterialIcon("")),
new TabBar.Tab("Buscar", new MaterialIcon("")),
new TabBar.Tab("Perfil", new MaterialIcon("")));
// One content Component per tab, in the SAME order as the tabs
tabBar.setContent(
telaInicio,
telaBusca,
telaPerfil);
tabBar.onTabChanged(index ->
{
// e.g.: load data on demand when the tab changes
if (index == 1) carregarBusca();
});
add(tabBar);
// Switch tabs programmatically, if needed:
tabBar.setActiveTab(2); // goes to "Profile"
Verification note (2026 code). Confirmed in source:
TabBar(Tab...),setContent(Component...),onTabChanged(TabChangedListener),setActiveTab(int). Behavior details: the tab bar slides horizontally when the tabs don’t fit; swiping the content panel switches the active tab and moves the indicator; the tab placement (top vs. bottom) and the indicator style come from the activeSkin’sTabBarStyle(e.g.,IOSSkinputs the tabs at the bottom). IfsetContentis not called, the bar shows only the tabs with no content panel.
Dig deeper
- Widget page: TabBar · Canonical source: Chapter 14
- Navigation between screens (alternative to tabs): Navigation