# Progress

> 进度指示器：可显示确定百分比的进度条、无限循环动画或旋转图标。

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

# Progress

`Progress` 是一个进度指示器，具有**三种**互斥的模式，在构造函数中选择（`mode` 字段是 `final` 的）：确定型进度条（已知百分比）、不确定型无限动画，或循环旋转的图标。动画在被添加时启动（`onAdd`，测试环境下除外），在被移除时停止（`onRemove`）。

> 🟢 · **包：** `dev.crossfly.ui` · **继承：** `Component` · **样式：** `ProgressStyle`

## 何时使用
- **`DETERMINATE_BAR`**：当有已知的百分比/值要显示时。
- **`INDETERMINATE`** / **`SPINNING_ICON`**：当持续时间未知时（加载中……）。

## 何时不使用
- 让用户通过拖动来**选择**一个值 → 使用 [`slider`](/docs/ui/widgets/slider)。

## 外观
取决于模式（`Progress.Mode`），以及在不确定型下取决于 `ProgressType`：

| `ProgressType` | 视觉效果 |
|---|---|
| `IOS` | 圆形加载图标（iOS 风格） |
| `FLUTTER` | 圆形指示器（easeInOut 时序） |
| `MATERIAL` | Material 线性进度条（连续循环） |
| `STRIPED` | 带动画的条纹进度条 |

进度条**只有水平方向**；高度为 `max(fontHeight * barHeight, 4)`。颜色来自 `ProgressStyle` 的 `filledColor`/`emptyColor`。

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

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;      // Styles.progress()
import dev.crossfly.ui.graphics.*;   // MaterialIcon

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 1) 确定型进度条 (0..100)，已填充 75%
      Progress barra = new Progress(0f, 100f);
      barra.setValue(75f);
      barra.style(Styles.progress().barHeight(1.5f));
      add(LAY_AUTO, barra);

      // 2) 不确定型进度条 (Material) —— 添加后自动动画
      Progress material = new Progress(ProgressType.MATERIAL);
      material.style(Styles.progress().barHeight(1.5f));
      add(LAY_AUTO, material);

      // 3) 循环旋转的图标
      Progress spinner = new Progress(new MaterialIcon("autorenew", 48));
      add(LAY_AUTO, spinner);
   }
}
```

> 下面的片段**只展示核心部分**（放入 `onShow()` 内的内容）。要运行它们，请将它们放入上面的 `MainWindow` 骨架中。

## 基本用法
```java
Progress barra = new Progress(0f, 100f);                // DETERMINATE_BAR 模式
barra.setValue(75f);                                    // 75%
barra.style(Styles.progress().barHeight(1.5f));
container.add(0f, barra);
```

## 构造函数
| 构造函数 | 模式 | 描述 |
|---|---|---|
| `Progress(float min, float max)` | `DETERMINATE_BAR` | 与 `value` 成比例的进度条（从 `min` 开始）。 |
| `Progress(ProgressType type)` | `INDETERMINATE` | 无限动画（Material/Flutter/iOS/Striped）。 |
| `Progress(Icon icon)` | `SPINNING_ICON` | 以连续循环旋转一个图标。 |

## 属性与自定义
| 属性 / 方法 | 类型 | 默认值 | 作用 |
|---|---|---|---|
| `setValue(float)` | `Progress`（流式） | — | **进度条模式**：设置值（带 `clamp`）并重新计算 `progress`。 |
| `mode` | `Progress.Mode`（字段，`final`） | 构造函数 | 操作模式（只读）。 |
| `value` / `min` / `max` | `float`（字段） | 构造函数 | 确定型进度条的状态。 |
| `progress` | `float`（字段） | — | 归一化进度 `[0,1]`（进度条）。 |
| `pivot(int, int)` | `Progress`（流式） | `-1,-1` | **图标模式**：旋转轴心（`-1,-1` = 自动居中）。 |

## 回调与事件
`Progress` 是**非交互的**：不暴露回调。随着工作推进，通过调用 `setValue(...)` 来更新进度条。

## 状态
- **DETERMINATE_BAR**：`setValue(v)` 对 `[min,max]` 进行 `clamp`，`progress = (value-min)/(max-min)`，`filledW = barW * progress`。
- **INDETERMINATE / SPINNING_ICON**：在 `onAdd` 启动、在 `onRemove` 停止的连续 `LoopAnimation`。

### 三种模式
```java
// 确定型进度条 0..50，已填充 35
Progress bar = new Progress(0f, 50f);
bar.setValue(35f);
bar.style(Styles.progress().barHeight(1.5f));
container.add(0f, bar);

// 不确定型进度条 (Material)
Progress material = new Progress(ProgressType.MATERIAL);
material.style(Styles.progress().barHeight(1.5f));
container.add(0f, material);

// 旋转的图标
Progress spinner = new Progress(new MaterialIcon("autorenew", 48));
container.add(0f, spinner);
```

## 最佳实践
- 只要知道百分比就使用 `DETERMINATE_BAR`；把不确定型留给未知的持续时间。
- 通过样式的 `filledColor`/`emptyColor` 自定义颜色，而不是继承子类。

## 常见错误
- 在不确定型/旋转图标模式下调用 `setValue`：没有有用的视觉效果（值只在 `DETERMINATE_BAR` 中起作用）。
- 期待垂直进度条或内嵌的百分比文本：进度条只有水平方向，且没有 prefix/suffix 标签。

## 另见
- 领域指南：[`ui/`](/docs/ui) · 食谱：[`cookbook/`](/docs/cookbook)
- 概念（动画与生命周期）：[`concepts/`](/docs/concepts)
- 相关组件：[`slider`](/docs/ui/widgets/slider)
