Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar

Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.

ListView

ListView es una lista desplazable de ítems de texto para selección, lista para embeber en cualquier container. Cada ítem se convierte en un “card” clicable. El modo de selección se fija en el constructor vía ItemType: SINGLE (tocar selecciona y confirma) o MULTIPLE (checkboxes + botón “Confirmar”).

A diferencia de VirtualListView, el ListView crea un componente por ítem (sin reciclaje) — es ideal para listas pequeñas/medianas (decenas de ítems), no para miles de filas.

🟡 · Paquete: dev.crossfly.ui · Extiende: Component · Estilo: ListViewStyle (ítems/header/botón) + WindowStyle (fondo, vía selectionWindowStyle())

Cuándo usar

  • Un selector embebido en una pantalla (menú de opciones, filtros, elección de categoría).
  • Pocas decenas de ítems de texto donde la altura exacta sin desplazamiento es útil (computeIdealHeight).
  • Multi-selección con confirmación explícita (MULTIPLE).

Cuándo NO usar

  • Listas grandes (cientos/miles) → usa VirtualListView, que recicla componentes.
  • Popup modal de elección → usa ListViewWindow, que envuelve el ListView en una Window.
  • Filas ricas con imagen/varios campos → usa itemFactory(...) o monta la lista a mano con ítems de lista.

Apariencia

Columna vertical de cards de texto centrados, con encabezado opcional (título + ícono de volver) y, en MULTIPLE, un botón “Confirmar” en el pie. En SINGLE cada card es un LabelItem; en MULTIPLE, un CheckLabelItem (checkbox + label).

Ejemplo completo (copiar, pegar y ejecutar)

package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: 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);   // las listas usan LAY_FILL (absorben la altura)
   }
}

Los fragmentos de abajo muestran solo el núcleo (lo que va dentro de onShow()). Para ejecutar, colócalos en el esqueleto MainWindow de arriba.

Uso básico

// SINGLE, sin encabezado, altura automática (sin scroll)
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);

Constructores

Constructor Descripción
ListView(String[] items, ItemType itemType) Lista sin título
ListView(String title, String[] items, ItemType itemType) Lista con título en el encabezado

ItemType (definido en UIConstants): SINGLE o MULTIPLE. El modo es inmutable tras la construcción.

Propiedades y personalización

Propiedad / método Tipo Por defecto Qué hace
addItem(String) ListView — Agrega un ítem (rebuild perezoso; ignora null)
addItems(String...) ListView — Agrega varios ítems (una sola invalidación)
showHeader(boolean) ListView true Muestra/oculta el encabezado (título + volver)
title(String) ListView null Define el título
confirmText(String) ListView "Confirmar" Texto del botón (solo MULTIPLE)
itemStyle(ComponentStyle) ListView tema Override de estilo de todos los ítems
confirmButtonStyle(ComponentStyle) ListView tema Estilo del botón de confirmar
headerStyle(LabelStyle) ListView tema Estilo del encabezado
itemFactory(ItemFactory) ListView null Fábrica de ítem personalizado (recibe text, index)
closeAction(Runnable) ListView null Acción de cierre (la ListViewWindow apunta a this::hide)
computeIdealHeight(int width) int — Altura exacta sin desplazamiento, o -1 si hay itemFactory

Consulta de selección

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

Callbacks y eventos

Callback Cuándo se dispara
onConfirm(Component.Action) SINGLE: al tocar un ítem. MULTIPLE: al tocar “Confirmar”

En SINGLE, el toque limpia la selección anterior, marca el índice, dispara onConfirm y llama a close(). En MULTIPLE, el toque alterna el checkbox del ítem; la confirmación sale del botón.

Estados

  • SINGLE — solo un ítem marcado a la vez; el toque ya confirma y cierra.
  • MULTIPLE — varios ítems marcables; estado consultable vía getSelectionState() incluso antes de confirmar.
  • El encabezado y el botón de pie son opcionales (dependen de showHeader/title y del ItemType).

MULTIPLE con 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);

Filas personalizadas con 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);

Buenas prácticas

  • Prefiere addItems(...) a varios addItem(...) — una única invalidación de layout.
  • Usa computeIdealHeight(width) cuando quieras una lista sin desplazamiento con altura exacta (devuelve -1 si hay itemFactory, pues los ítems personalizados no son medibles genéricamente).
  • La reconstrucción de los ítems es perezosa (ocurre en el próximo layout), incluso cuando el ancho cambia.

Errores comunes

  • Usar ListView para miles de ítems — no recicla; la memoria crece linealmente. Migra a VirtualListView.
  • Esperar onConfirm en MULTIPLE a cada toque — en MULTIPLE el callback solo se dispara en el botón “Confirmar”; consulta getSelectionState() para reaccionar a cada marcación.
  • Asumir que existe un constructor sin ítems — el constructor exige items e ItemType; comienza con new String[]{} y usa addItems(...).

Ver también

¿Te resultó útil esta página?