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

ListView

ListView é uma lista rolável de itens de texto para seleção, pronta para embutir em qualquer container. Cada item vira um “card” clicável. O modo de seleção é fixado no construtor via ItemType: SINGLE (toque seleciona e confirma) ou MULTIPLE (checkboxes + botão “Confirmar”).

Ao contrário de VirtualListView, o ListView cria um componente por item (sem reciclagem) — é ideal para listas pequenas/médias (dezenas de itens), não para milhares de linhas.

🟡 · Pacote: dev.crossfly.ui · Estende: Component · Estilo: ListViewStyle (itens/header/botão) + WindowStyle (fundo, via selectionWindowStyle())

Quando usar

  • Um seletor embutido numa tela (menu de opções, filtros, escolha de categoria).
  • Poucas dezenas de itens de texto onde altura exata sem rolagem é útil (computeIdealHeight).
  • Multi-seleção com confirmação explícita (MULTIPLE).

Quando NÃO usar

  • Listas grandes (centenas/milhares) → use VirtualListView, que recicla componentes.
  • Popup modal de escolha → use ListViewWindow, que envolve o ListView numa Window.
  • Linhas ricas com imagem/vários campos → use itemFactory(...) ou monte a lista à mão com itens de lista.

Aparência

Coluna vertical de cards de texto centralizados, com cabeçalho opcional (título + ícone de voltar) e, em MULTIPLE, um botão “Confirmar” no rodapé. Em SINGLE cada card é um LabelItem; em MULTIPLE, um CheckLabelItem (checkbox + label).

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());

      ListView list = new ListView(new String[]{"Um", "Dois", "Três"}, ListView.ItemType.SINGLE)
         .showHeader(false);
      list.onConfirm(e -> System.out.println("Escolhido: " + list.getSelectedText()));

      add(LAY_FILL, list);   // listas usam LAY_FILL (absorvem a altura)
   }
}

Os trechos abaixo mostram só o miolo (o que vai dentro de onShow()). Para rodar, coloque-os no esqueleto MainWindow acima.

Uso básico

// SINGLE, sem cabeçalho, altura automática (sem rolagem)
ListView list = new ListView(new String[]{"Um", "Dois", "Três"}, ListView.ItemType.SINGLE)
   .showHeader(false);
list.onConfirm(e -> System.out.println("Escolhido: " + list.getSelectedText()));
contents.add(.95f, list);

Construtores

Construtor Descrição
ListView(String[] items, ItemType itemType) Lista sem título
ListView(String title, String[] items, ItemType itemType) Lista com título no cabeçalho

ItemType (definido em UIConstants): SINGLE ou MULTIPLE. O modo é imutável após a construção.

Propriedades e personalização

Propriedade / método Tipo Padrão O que faz
addItem(String) ListView — Adiciona um item (rebuild preguiçoso; ignora null)
addItems(String...) ListView — Adiciona vários itens (uma só invalidação)
showHeader(boolean) ListView true Mostra/esconde o cabeçalho (título + voltar)
title(String) ListView null Define o título
confirmText(String) ListView "Confirmar" Texto do botão (só MULTIPLE)
itemStyle(ComponentStyle) ListView tema Override de estilo de todos os itens
confirmButtonStyle(ComponentStyle) ListView tema Estilo do botão de confirmar
headerStyle(LabelStyle) ListView tema Estilo do cabeçalho
itemFactory(ItemFactory) ListView null Fábrica de item customizado (recebe text, index)
closeAction(Runnable) ListView null Ação de fechamento (a ListViewWindow aponta para this::hide)
computeIdealHeight(int width) int — Altura exata sem rolagem, ou -1 se houver itemFactory

Consulta de seleção

getSelectedCount(), getSelectedIndex(), getSelectedText(), getSelectedIndices(), getSelectedTexts(), isSelected(int), getSelectionState() (boolean[]).

Callbacks e eventos

Callback Quando dispara
onConfirm(Component.Action) SINGLE: ao tocar um item. MULTIPLE: ao tocar “Confirmar”

Em SINGLE, o toque limpa a seleção anterior, marca o índice, dispara onConfirm e chama close(). Em MULTIPLE, o toque alterna o checkbox do item; a confirmação sai do botão.

Estados

  • SINGLE — apenas um item marcado por vez; o toque já confirma e fecha.
  • MULTIPLE — vários itens marcáveis; estado consultável via getSelectionState() mesmo antes de confirmar.
  • Cabeçalho e botão de rodapé são opcionais (dependem de showHeader/title e do ItemType).

MULTIPLE com altura automática

ListView multi = new ListView(new String[]{"Vermelho", "Verde", "Azul"},
      ListView.ItemType.MULTIPLE)
   .showHeader(false)
   .confirmText("Aplicar");
multi.getStyle().autoHeight(Relative.ofFont(9f));
multi.onConfirm(e -> {
   for (String t : multi.getSelectedTexts())
      System.out.println("marcado: " + t);
});
contents.add(.95f, multi);

Linhas customizadas com itemFactory

ListView list = new ListView(labels, ListView.ItemType.SINGLE).showHeader(false);
list.itemFactory((text, index) -> {
   Component row = new Component();
   row.style(Styles.component().pressable().ingap(Gap.ofFont(.3f)));
   row.setLayout(new GridLayout(Position.START, Position.CENTER));
   row.add(new Label(text));
   return row;
});
list.onConfirm(e -> System.out.println("idx = " + list.getSelectedIndex()));
contents.add(.95f, list);

Boas práticas

  • Prefira addItems(...) a vários addItem(...) — uma única invalidação de layout.
  • Use computeIdealHeight(width) quando quiser uma lista sem rolagem com altura exata (retorna -1 se houver itemFactory, pois itens customizados não são mensuráveis genericamente).
  • A reconstrução dos itens é preguiçosa (acontece no próximo layout), inclusive quando a largura muda.

Erros comuns

  • Usar ListView para milhares de itens — ele não recicla; a memória cresce linearmente. Migre para VirtualListView.
  • Esperar onConfirm em MULTIPLE a cada toque — em MULTIPLE o callback só dispara no botão “Confirmar”; consulte getSelectionState() para reagir a cada marcação.
  • Assumir que existe construtor sem itens — o construtor exige items e ItemType; comece com new String[]{} e use addItems(...).

Veja também

Esta página foi útil?