# 屏幕转场

> 通过声明 WindowStyle.transition 来为窗口切换（淡入淡出/滑动/缩放）添加动画。

Source: https://crossfly.dev/zh/docs/ui/animations/screen-transitions — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 屏幕转场

在窗口 `show()`/`hide()` 时，CrossFly 可以通过捕捉切换**前**和**后**的画面并在两者之间插值来为切换添加动画。
你在 `WindowStyle` 中**声明**该效果；框架会自行触发转场。

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

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

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      // 在挂载 UI 之前声明过渡（"之前"状态在首次 paint 时捕获）。
      // getStyle() 在此推断 WindowStyle，此处定义了 transition(...)。
      getStyle().transition(UIConstants.Transition.SLIDE_LEFT, 0.4f);   // 效果 + 时长（秒）

      setLayout(new VerticalLayout());
      Label titulo = new Label("Nova tela");
      add(LAY_AUTO, titulo);

      Button avancar = new Button("Avançar");
      add(LAY_AUTO, avancar);
      // 当压入另一个带 SLIDE_LEFT 过渡的窗口时，框架会自动为切换添加动画：
      avancar.onAction(c -> new MainWindow().show());
   }
}
```
> 下面的片段只展示了**核心部分**（放入 `onShow()` 内部的内容）。要运行它们，请将其放入上面的 `MainWindow` 骨架中。

## 声明式的方式（推荐）
在窗口样式中定义效果 — 在 `onShow()` 中，任何内容显示之前：
```java
@Override public void onShow() throws Exception {
   super.onShow();
   getStyle().transition(UIConstants.Transition.SLIDE_LEFT, 0.4f);  // 效果 + 时长（秒）
   // … 挂载 UI …
}
```
或通过 `WindowStyle` 的字段/流式方法：
```java
getStyle().transition = UIConstants.Transition.FADE;   // 公有字段
getStyle().transitionDuration = 0.3f;
// 流式等价写法：
getStyle().transition(UIConstants.Transition.FADE).transitionDuration(0.3f);
```

## 可用效果（`UIConstants.Transition`）
| 值 | 效果 |
|---|---|
| `NONE` | 即时切换（默认） |
| `FADE` | 一个界面淡入覆盖另一个 |
| `SLIDE_LEFT` / `SLIDE_RIGHT` | 沿水平轴滑动 |
| `SLIDE_UP` / `SLIDE_DOWN` | 沿垂直轴滑动 |
| `SCALE` | 新界面从中心放大 |
| `SCALE_DOWN` | 当前界面向中心缩小 |

> 默认值：`WindowStyle.transition` 初始为 `NONE`，`transitionDuration` 初始为 `0.5s`。**Picker** 已经
> 默认使用 `FADE`。

## 底层原理
`ScreenTransition.begin(Transition, duration)` 将当前界面捕捉为"之前"，将新界面在下一帧捕捉为
"之后"并进行插值（使用内部的 `AlphaAnimation`）。你通常**不**会去调用它 —
当 `transition != NONE` 时，`Window.show()`/`hide()` 会调用它。

## 最佳实践
- 根据**导航意图**选择效果：`SLIDE_LEFT` 用于前进，`SLIDE_RIGHT`/`SCALE_DOWN`
  用于返回。
- 保持时长较短（0.25–0.4s）— 过长的转场会造成干扰。
- 在 `onShow()` 中定义转场（在窗口被绘制之前）。

## 常见错误
- 定义转场太晚（在第一次 paint 之后）— "之前"的画面已经改变了。
- 时长过长导致导航变慢。

## 另请参阅
- [数值动画](/docs/ui/animations/value-animations) · [窗口栈](/docs/ui/navigation/the-window-stack)
