Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar

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 (via getSkin().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 esqueleto MainWindow acima.

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, activeIndex troca e onTabChanged dispara.
  • 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 Skin cujo TabBarStyle.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

  • setContent com contagem errada → IllegalArgumentException. Passe exatamente uma view por aba.
  • Esperar que setActiveTab dispare onTabChanged para o índice já ativo — é no-op quando index == activeIndex.

Veja também

Esta página foi útil?