Como criar um pulso contínuo (loop)
Propósito. Fazer algo pulsar/piscar indefinidamente (indicador de “carregando”, brilho, respiração de um botão). LoopAnimation cicla um valor de 0 → 1 repetidamente, com ou sem easing, sem onComplete (é infinita — você a para com stop()).
APIs usadas
new LoopAnimation(float duration [, float fps, boolean easeInOut])— cada ciclo duradurationsegundos e reinicia sozinho.fpsdefault 60;easeInOutdefaultfalse(linear). ComeaseInOut=true, aplica ease-in-out cubic por ciclo.LoopAnimation.onUpdate(Runnable)— callback a cada frame; leiagetValue()(0–1, progresso do ciclo atual).LoopAnimation.getValue()— progresso atual do ciclo.LoopAnimation.start()/stop()— inicia / interrompe o loop. Não háonCompletenemcancel()— é infinita por natureza.Component.alpha(float)— aplica opacidade (para efeito de “respiração”).Component.repaint()— estático; obrigatório noonUpdate.
Exemplo completo (copiar, colar e rodar)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.animation.*;
/** Tela principal executável: pulsa um "●" em loop; pare o loop ao fechar a tela. */
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, com easing (pulso suave)
pulse = new LoopAnimation(1f, 60f, true);
pulse.onUpdate(() ->
{
// valor vai 0 → 1 e reinicia; mapeia para opacidade 0.3 → 1.0
float v = 0.3f + 0.7f * pulse.getValue();
dot.alpha(v);
Component.repaint();
})
.start();
// botão que encerra o pulso (ex.: quando o carregamento terminar)
add(new Button("Parar").onAction(e -> pulse.stop()));
}
@Override
public void onRemove()
{
// Pare ao sair da tela para não deixar um loop órfão animando fora da tela.
if (pulse != null) pulse.stop();
super.onRemove();
}
}
O trecho abaixo mostra só o miolo. Para rodar, coloque-o no esqueleto
MainWindowacima.
Trecho mínimo
// verificado na fonte: LoopAnimation(duration, fps, easeInOut); sem onComplete; pare com stop()
Label dot = new Label("●");
add(dot);
// ciclo de 1 s, 60 fps, com easing (pulso suave)
LoopAnimation pulse = new LoopAnimation(1f, 60f, true);
pulse.onUpdate(() ->
{
// valor vai 0 → 1 e reinicia; mapeia para opacidade 0.3 → 1.0
float v = 0.3f + 0.7f * pulse.getValue();
dot.alpha(v);
Component.repaint();
})
.start();
// mais tarde, para encerrar o pulso (ex.: quando o carregamento terminar):
pulse.stop();
Cuidados importantes:
- Guarde a referência (
pulse) para poder chamarstop(). UmaLoopAnimationsemstop()roda para sempre e consome CPU/GPU continuamente (cada frame chamarepaint()). - Pare ao sair da tela: chame
pulse.stop()quando aWindowfor fechada (onRemove/hide) para não deixar um loop órfão animando fora da tela. getValue()volta a 0 no início de cada ciclo. Para um pulso “vai-e-volta” (0→1→0), mapeie com uma função triangular ou seno sobregetValue().
Aprofunde-se
- Animações de valor · Press e feedback
- Receita irmã: Fade de um componente · Mover um componente
Esta página foi útil?Obrigado pelo feedback!