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.

Cómo hacer un Component desplazable y ajustar el overscroll

Propósito. Cualquier Component puede convertirse en un contenedor desplazable: basta declarar la dirección con setScrollable(ScrollDirection). Si el contenido (la suma de las alturas de los hijos) excede el área visible, el ScrollEngine se encarga de pan, momentum, fling y del overscroll (efecto elástico al tirar más allá del límite).

APIs usadas

  • Component.setScrollable(ScrollDirection dir, ScrollEngine... engine) — habilita scroll. engine es opcional (default: ScrollEngine nuevo). Pasa null como dir para deshabilitar.
  • UIConstants.ScrollDirection — enum con tres valores: HORIZONTAL, VERTICAL, BOTH.
  • Component.isScrollable() — si el componente está desplazable.
  • Component.scrollable() — retorna el objeto Scrollable (con .engine), o null.
  • Component.setShowScrollPosition(boolean) — muestra/oculta el indicador de posición de scroll.
  • ScrollEngine.setOverscroll(boolean x, boolean y) — activa/desactiva el efecto elástico por eje. Default: ambos true.
  • ScrollEngine.setupOverscroll(float distance, float speedMin, float speedMax) — ajusta distancia y velocidad de retorno del overscroll.
  • ScrollEngine.setScrollListener(ScrollListener listener) — callback en cada cambio de offset (recibe vx, vy).
  • ScrollEngine.scrollTo(float x, float y) / scrollToStartSmooth() / scrollToEndSmooth() — reposiciona el scroll.
  • ScrollEngine.setOverscrollEffect(OverscrollEffect effect) — estático: define/desactiva (null) la curva gris de borde global; personalizable via new OverscrollEffect().setColor(...).setMaxAlpha(...).setMaxArcHeight(...).

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

      Component painel = new Component();
      painel.setLayout(new GridLayout(Position.CENTER, Position.START));
      for (int i = 0; i < 60; i++)
         painel.add(.95f, new Label("Linha " + i));

      painel.setScrollable(ScrollDirection.VERTICAL);   // desplaza en el eje Y

      // ajustes opcionales en el motor de scroll:
      painel.scrollable().engine.setOverscroll(true, false);   // elástico solo en la vertical
      painel.setShowScrollPosition(true);                       // indicador de posición
      painel.scrollable().engine.setScrollListener((vx, vy) ->
         Debug.log("scrollY = " + vy));                         // reacciona al scroll

      add(LAY_FILL, painel);
   }
}

El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colócalo en el esqueleto MainWindow de arriba.

Fragmento mínimo

// verificado en la fuente: Component.setScrollable (línea ~1027) + ScrollEngine.java
Component painel = new Component();
painel.setLayout(new GridLayout(Position.CENTER, Position.START));
for (int i = 0; i < 60; i++)
   painel.add(.95f, new Label("Linha " + i));

painel.setScrollable(ScrollDirection.VERTICAL);   // desplaza en el eje Y

// ajustes opcionales en el motor de scroll:
painel.scrollable().engine.setOverscroll(true, false);   // elástico solo en la vertical
painel.setShowScrollPosition(true);                       // indicador de posición
painel.scrollable().engine.setScrollListener((vx, vy) ->
   Debug.log("scrollY = " + vy));                         // reacciona al scroll

layout.add(1f, painel);

Reposicionando por código:

painel.scrollable().engine.scrollToStartSmooth();   // vuelve al tope con animación
painel.scrollable().engine.scrollTo(0, 500);        // salta al offset y=500 px

Nota honesta: no hay pull-to-refresh listo

El framework no ofrece un widget de “pull-to-refresh” (tirar-para-actualizar) listo. Lo que existe es el efecto de overscroll (curva elástica al tirar más allá del límite), que es puramente visual/físico — no expone un callback de “soltó después de tirar X píxeles” para que dispares un refresh. Si necesitas ese comportamiento, tendrás que construirlo manualmente monitoreando el offset via setScrollListener y detectando el overscroll más allá de un umbral. Para listas grandes con recarga de datos, prefiere VirtualListView.reloadData() accionado por un botón o gesto propio.

Profundiza

  • Las listas enormes ya vienen desplazables por defecto (el VirtualListView llama a setScrollable(VERTICAL) internamente): mira lista-virtual-grande.md.
¿Te resultó útil esta página?