# Como mover um componente animando sua posição

> Deslizar um componente de um ponto a outro com PositionAnimation (interpolação linear em pixels).

Source: https://crossfly.dev/pt/docs/cookbook/anim/mover-componente — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Como mover um componente animando sua posição

**Propósito.** Animar a **posição em pixels** de um componente (ex.: deslizar um card da direita para o centro). `PositionAnimation` interpola linearmente e **não** é clampada a [0,1] — ideal para coordenadas.

## APIs usadas
- `new PositionAnimation(float start, float end, float duration [, float fps])` — interpola `start → end` **linearmente**, **sem clamp**; `duration` em segundos; `fps` opcional (default 60).
- `PositionAnimation.onUpdate(Runnable)` / `onComplete(Runnable)` / `getValue()` / `start()` / `stop()` / `cancel()` — mesma família de `AlphaAnimation`.
- `Component.setX(int)` / `Component.setY(int)` — reposicionam o componente (retornam `Component`). Alternativa: `setBounds(int x, int y, int w, int h)` quando também mudar tamanho.
- `Component.getY()` / `getWidth()` / `getHeight()` — para preservar os eixos que não estão animando.
- `Component.repaint()` — estático; obrigatório no `onUpdate` (render sob demanda).

## Exemplo completo (copiar, colar e rodar)
```java
package com.exemplo;

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

/** Tela principal executável: desliza um card da direita para o centro ao abrir. */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Card card = new Card();
      add(card);

      int fromX = Screen.width;          // começa fora da tela, à direita
      int toX   = (Screen.width - card.width) / 2;   // centraliza horizontalmente

      PositionAnimation slide = new PositionAnimation(fromX, toX, 0.4f);   // 400 ms
      slide.onUpdate(() ->
         {
            card.x = (int) slide.getValue();     // move só o eixo X; Y permanece (x é campo público)
            Component.repaint();                 // sem isto o quadro não é redesenhado
         })
         .onComplete(() -> Component.repaint())
         .start();
   }
}
```

> O trecho abaixo mostra **só o miolo**. Para rodar, coloque-o no esqueleto `MainWindow` acima.

## Trecho mínimo
```java
// verificado na fonte: PositionAnimation linear sem clamp; Component.setX(int)/setY(int); repaint() estático
Card card = new Card();
add(card);

int fromX = Screen.width;          // começa fora da tela, à direita
int toX   = (Screen.width - card.getWidth()) / 2;   // centraliza horizontalmente

PositionAnimation slide = new PositionAnimation(fromX, toX, 0.4f);   // 400 ms
slide.onUpdate(() ->
   {
      card.setX((int) slide.getValue());   // move só o eixo X; Y permanece
      Component.repaint();                 // sem isto o quadro não é redesenhado
   })
   .onComplete(() -> Component.repaint())
   .start();
```

Detalhes:

- Se precisar mover em X **e** Y ao mesmo tempo, use **duas** `PositionAnimation` (uma por eixo) ou aplique `setBounds(x, y, w, h)` no `onUpdate` computando ambos.
- `setX`/`setY` alteram a posição **absoluta** no pai; em telas com layout automático, prefira animar componentes cujo bounds você controla diretamente (evite brigar com o `Layout`).
- Diferente de `AlphaAnimation`, aqui **não** há easing: o movimento é constante. Para movimento suave, encadeie um easing na sua própria função ou combine com `AlphaAnimation` para o efeito de opacidade.

## Aprofunde-se
- [Animações de valor](/docs/ui/animations/value-animations)
- Receita irmã: [Fade de um componente](/docs/cookbook/anim/fade) · [Pulso em loop](/docs/cookbook/anim/pulso-loop)
- Relacionado: [Abrir e fechar uma tela](/docs/cookbook/nav/abrir-tela)
