TabBar
TabBar é uma barra de abas: uma tira de botões (tab strip) + um painel de conteúdo rolável horizontalmente com snap por página (via PageScrollEngine). Tocar numa aba rola o conteúdo até a página correspondente; arrastar o conteúdo troca a aba ativa. Um indicador animado acompanha a aba ativa.
A estética (indicador, abas no topo ou rodapé, cores) vem do Skin ativo (TabBarStyle). Cada aba é descrita por um TabBar.Tab (texto, ícone ou ambos).
🟡 · Pacote:
dev.crossfly.ui· Estende:Component· Estilo:TabBarStyle(viagetSkin().tabBar())
Quando usar
- Navegação entre 2–5 seções de uma tela (Home / Buscar / Perfil).
- Conteúdo paginado com gesto de swipe entre páginas + abas sincronizadas.
Quando NÃO usar
- Muitas seções que não cabem (a tira rola, mas fica menos legível) → considere outra navegação.
Aparência
Tira de abas de largura igual (1/n); se elas não couberem, a tira vira rolável horizontalmente e as abas passam a largura automática. O indicador desliza sob (ou sobre, se tabsAtBottom) a aba ativa. O painel de conteúdo mostra uma página por vez com snap.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** Tela principal executável. Aponte o launcher (classname) e rode: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
// Uma view de conteúdo por aba (a contagem TEM que casar com o número de abas).
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); // a TabBar absorve a altura restante
}
}
Os trechos abaixo mostram só o miolo (o que vai dentro de
onShow()). Para rodar, coloque-os no esqueletoMainWindowacima.
Uso básico
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);
Construtores
| Construtor | Descrição |
|---|---|
TabBar(Tab... tabs) |
Cria a barra com as abas (activeIndex = 0) |
TabBar.Tab (descritor de aba)
| Construtor | Resultado |
|---|---|
Tab(String text) |
Só texto (TextPos.NONE) |
Tab(Icon icon) |
Só ícone (TextPos.NONE) |
Tab(String text, Icon icon) |
Texto + ícone (TextPos.TEXT_AT_BOTTOM) |
Tab(String text, Icon icon, TextPos textPos) |
Texto + ícone com posição customizada |
Propriedades e personalização
| Propriedade / método | Tipo | O que faz |
|---|---|---|
setContent(Component...) |
TabBar |
Conteúdo por aba (a contagem deve casar com as abas, senão IllegalArgumentException) |
setActiveTab(int) |
TabBar |
Ativa uma aba programaticamente (com animação/scroll); no-op se inválido ou já ativo |
getActiveIndex() |
int |
Índice da aba ativa |
getTabs() |
Tab[] |
Descritores das abas |
getStrip() / getTabButtons() / getContentPanel() |
— | Acesso aos internos |
getIndicatorX() / getIndicatorW() |
float |
Posição/largura atuais do indicador (para pintura no Design) |
Callbacks e eventos
| Callback | Quando dispara |
|---|---|
onTabChanged(TabChangedListener) |
Ao trocar de aba, por toque, swipe ou setActiveTab(...) |
TabChangedListener é funcional: void onTabChanged(int index).
Estados
- Ativa — só uma aba por vez; o indicador anima até ela (duração
TabBarStyle.switchDuration). - Swipe do usuário — o indicador interpola continuamente entre abas vizinhas; ao cruzar para outra página,
activeIndextroca eonTabChangeddispara. - Programático —
setActiveTab/toque travam a sincronização até a animação de scroll chegar ao alvo.
Abas só de texto
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);
Troca programática de aba
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);
// ... mais tarde:
tabs.setActiveTab(2); // anima até a aba C
Boas práticas
- A contagem de
setContent(...)tem que bater com o número de abas. - Para abas no rodapé (estilo iOS), use um
SkincujoTabBarStyle.tabsAtBottom = true— o layout e o indicador se ajustam sozinhos. - Não force largura fixa nas abas: se não couberem, a tira rola por conta própria.
Erros comuns
setContentcom contagem errada →IllegalArgumentException. Passe exatamente uma view por aba.- Esperar que
setActiveTabdispareonTabChangedpara o índice já ativo — é no-op quandoindex == activeIndex.