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 crear un pulso continuo (loop)
Propósito. Hacer que algo pulse/parpadee indefinidamente (indicador de “cargando”, brillo, respiración de un botón). LoopAnimation cicla un valor de 0 → 1 repetidamente, con o sin easing, sin onComplete (es infinita — la detienes con stop()).
APIs usadas
new LoopAnimation(float duration [, float fps, boolean easeInOut])— cada ciclo duradurationsegundos y se reinicia solo.fpspor defecto 60;easeInOutpor defectofalse(linear). ConeaseInOut=true, aplica ease-in-out cubic por ciclo.LoopAnimation.onUpdate(Runnable)— callback en cada frame; leegetValue()(0–1, progreso del ciclo actual).LoopAnimation.getValue()— progreso actual del ciclo.LoopAnimation.start()/stop()— inicia / interrumpe el loop. No hayonCompletenicancel()— es infinita por naturaleza.Component.alpha(float)— aplica opacidad (para el efecto de “respiración”).Component.repaint()— estático; obligatorio en elonUpdate.
Ejemplo completo (copiar, pegar y ejecutar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.animation.*;
/** Pantalla principal ejecutable: pulsa un "●" en loop; detén el loop al cerrar la pantalla. */
public class MainWindow extends Window
{
private LoopAnimation pulse;
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
Label dot = new Label("●");
add(dot);
// ciclo de 1 s, 60 fps, con easing (pulso suave)
pulse = new LoopAnimation(1f, 60f, true);
pulse.onUpdate(() ->
{
// el valor va 0 → 1 y reinicia; mapea a opacidad 0.3 → 1.0
float v = 0.3f + 0.7f * pulse.getValue();
dot.alpha(v);
Component.repaint();
})
.start();
// botón que finaliza el pulso (ej.: cuando la carga termina)
add(new Button("Parar").onAction(e -> pulse.stop()));
}
@Override
public void onRemove()
{
// Detén al salir de la pantalla para no dejar un loop huérfano animando fuera de la pantalla.
if (pulse != null) pulse.stop();
super.onRemove();
}
}
El fragmento de abajo muestra solo el núcleo. Para ejecutarlo, colócalo en el esqueleto
MainWindowde arriba.
Fragmento mínimo
// verificado en la fuente: LoopAnimation(duration, fps, easeInOut); sin onComplete; detén con stop()
Label dot = new Label("●");
add(dot);
// ciclo de 1 s, 60 fps, con easing (pulso suave)
LoopAnimation pulse = new LoopAnimation(1f, 60f, true);
pulse.onUpdate(() ->
{
// el valor va 0 → 1 y reinicia; mapea a opacidad 0.3 → 1.0
float v = 0.3f + 0.7f * pulse.getValue();
dot.alpha(v);
Component.repaint();
})
.start();
// más tarde, para finalizar el pulso (ej.: cuando la carga termina):
pulse.stop();
Cuidados importantes:
- Guarda la referencia (
pulse) para poder llamar astop(). UnaLoopAnimationsinstop()corre para siempre y consume CPU/GPU continuamente (cada frame llama arepaint()). - Detén al salir de la pantalla: llama a
pulse.stop()cuando laWindowse cierre (onRemove/hide) para no dejar un loop huérfano animando fuera de la pantalla. getValue()vuelve a 0 al inicio de cada ciclo. Para un pulso “ida y vuelta” (0→1→0), mapea con una función triangular o seno sobregetValue().
Profundiza
- Animaciones de valor · Press y feedback
- Receta hermana: Fade de un componente · Mover un componente
¿Te resultó útil esta página?¡Gracias por tu opinión!