# 如何为组件添加淡入淡出（出现/消失）效果

> 使用 AlphaAnimation 为组件的不透明度添加动画，通过 alpha() 应用该值并按需重绘。

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

# 如何为组件添加淡入淡出（出现/消失）效果

**目的。** 让组件平滑地出现（0 → 1）或消失（1 → 0）。`AlphaAnimation` 以 ease-in-out 插值一个 `float`；你将该值应用到组件的不透明度并强制重绘。

## 使用的 API
- `new AlphaAnimation(float start, float end, float duration [, float fps])` —— 创建动画。`start`/`end` 会**被夹紧到 [0,1]**；采用 **ease-in-out 三次**插值；`duration` 以秒计；`fps` 可选（默认 60）。
- `AlphaAnimation.onUpdate(Runnable)` —— 每帧的回调；在此读取 `getValue()`。
- `AlphaAnimation.onComplete(Runnable)` —— 到达 `end` 时的回调（也会由 `stop()` 触发）。
- `AlphaAnimation.getValue()` —— 当前的插值。
- `AlphaAnimation.start()` / `stop()` / `cancel()` —— 启动 / 停止（触发 `onComplete`）/ 取消（不触发）。
- `Component.alpha(float)` —— 设置组件的不透明度（0–1，会被夹紧）。**Javadoc 偏差：**文档提到 `setAlpha`，但真正的方法是 `alpha(...)`。
- `Component.repaint()` —— **静态**方法；请求重新渲染（CrossFly 按需渲染，因此必须在 `onUpdate` 内调用）。

## 完整示例（复制、粘贴并运行）
```java
package com.exemplo;

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

/** 可执行的主界面：打开时对 Label 应用 fade-in。 */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Label c = new Label("Olá");
      add(c);

      // 先声明变量，以便在 onUpdate 内读取 getValue()。
      AlphaAnimation anim = new AlphaAnimation(0f, 1f, 0.3f);       // 300 ms，0 → 1
      anim.onUpdate(() ->
         {
            c.alpha(anim.getValue());   // 应用不透明度
            Component.repaint();        // 按需渲染：没有它，帧不会重绘
         })
         .onComplete(() -> Component.repaint())
         .start();
   }
}
```

> 下面的代码片段仅展示**核心部分**。要运行它，请将其放入上面的 `MainWindow` 骨架中。

## 最小片段
```java
// 已在源码核实：AlphaAnimation clamp [0,1] ease-in-out；Component.alpha(float)；Component.repaint() 静态
Label c = new Label("Olá");
add(c);

// 先声明变量，以便在 onUpdate 内读取 getValue()。
AlphaAnimation anim = new AlphaAnimation(0f, 1f, 0.3f);       // 300 ms，0 → 1
anim.onUpdate(() ->
   {
      c.alpha(anim.getValue());   // 应用不透明度
      Component.repaint();        // 按需渲染：没有它，帧不会重绘
   })
   .onComplete(() -> Component.repaint())
   .start();
```

注意事项：

- `alpha(1f)`（或 `>= 0.999`）会移除不透明度属性（组件 100% 不透明）；`alpha(0f)` 使其不可见但仍存在于布局中。
- 对于淡出，请使用 `new AlphaAnimation(1f, 0f, 0.3f)`，并在 `onComplete` 中根据需要 `hide()`/移除组件。
- **始终**在 `onUpdate` 中调用 `Component.repaint()` —— CrossFly 仅在被请求时才重绘。

## 深入了解
- [值动画](/docs/ui/animations/value-animations)
- 姊妹配方：[循环脉冲](/docs/cookbook/anim/pulso-loop) · [移动组件](/docs/cookbook/anim/mover-componente)
- 相关：[打开和关闭屏幕](/docs/cookbook/nav/abrir-tela)
