Log Entry

SF Symbols 动画完全指南

怎么漂亮的使用SF Symbol

SF Symbols 动画完全指南

目录

  1. SF Symbols 动画概览
  2. 七种动画效果详解
  3. UIKit / Objective-C 实战
  4. 创建自定义动画符号
  5. 符号组件(Symbol Components)
  6. 兼容性与导出
  7. 最佳实践
  8. SF Symbols 7 新特性(WWDC 2025)

1. SF Symbols 动画概览

SF Symbols 5(随 iOS 17 / macOS Sonoma 推出)引入了一套完整的符号动画体系。相比之前静态的图像切换,新的动画 API 让符号本身"活"了起来——弹跳、脉冲、出现/消失、渐变替换,每种效果都由苹果精心调校,开发者无需手写关键帧动画

当然如果你想的话也可以在SF Symbol中自定义动画,然后导入到项目中

三大框架均支持:

框架 主要 API
UIKit addSymbolEffect: / setSymbolImage:contentTransition:
AppKit addSymbolEffect: / setSymbolImage:contentTransition:
SwiftUI .symbolEffect() 修饰符

本文以 UIKit + Objective-C 为主


2. 七种动画效果详解

由于使用英文可以更好的表示意思,并且可以在代码中体现的清晰一些,这里主要使用英文来做主名字

SF Symbols 5 提供 7 种预设动画,按"行为类型"分为四类:

效果 行为类型 说明
Bounce(弹跳) 离散 触发后播放一次弹跳
Pulse(脉冲) 离散 / 无限 符号图层透明度脉动闪烁
Variable Color(可变颜色) 离散 / 无限 按图层顺序渐次点亮颜色
Scale(缩放) 无限 持续放大或缩小
Appear(出现) 过渡 / 无限 符号淡入
Disappear(消失) 过渡 / 无限 符号淡出
Replace(替换) 内容过渡 从一个符号动画切换到另一个

行为类型说明

  • 离散(Discrete):动画播放一次后自动结束,适合响应按钮点击等事件。
  • 无限(Indefinite):持续播放直到手动移除,适合表示"进行中"的状态。
  • 过渡(Transition):视图进入或离开层级时触发,分为两个空间(见第 3 节)。
  • 内容过渡(Content Transition):在同一 ImageView 中将符号 A 平滑切换为符号 B。

3. UIKit / Objective-C 实战

3.1 无限效果 —— Variable Color(可变颜色)

适合"正在连接 Wi-Fi""正在加载"等持续状态。

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"wifi.router"]];
 
 // 添加可变颜色动画(迭代 + 反向)
 [imageView addSymbolEffect:[NSSymbolVariableColorEffect effect].iterative.reversing];
 
 // 同时叠加缩放效果
 [imageView addSymbolEffect:[NSSymbolScaleEffect effectScalingUp]];

CleanShot_2026-03-15_at_16.04.22.gif

移除无限效果:

// 按类型移除
 [imageView removeSymbolEffectOfType:[NSSymbolVariableColorEffect effect]];

3.2 离散效果 —— Bounce(弹跳)

适合收到消息、完成操作等需要短暂吸引注意力的场景。

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"antenna.radiowaves.left.and.right"]];
 
 // 弹跳两次
 NSSymbolEffectOptions *options = [NSSymbolEffectOptions optionsWithRepeatCount:2];
 [imageView addSymbolEffect:[NSSymbolBounceEffect effect] options:options animated:YES];

CleanShot_2026-03-15_at_16.06.05.gif

3.3 内容过渡 —— Replace(替换)

适合播放/暂停按钮、收藏/取消收藏等状态切换场景。

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"play.fill"]];
 
 // 切换到暂停图标,使用 offUp 方向的替换动画
 UIImage *pauseImage = [UIImage systemImageNamed:@"pause.fill"];
 [imageView setSymbolImage:pauseImage
         contentTransition:[[NSSymbolReplaceContentTransition effect] offUp]];

CleanShot_2026-03-15_at_16.07.15.gif

3.4 出现 / 消失 —— 无限行为

无限行为下,视图仍保留在视图层级中,布局不变,只是视觉上不可见。

UIImageView *moonView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"moon.stars"]];
 
 // 消失(视图依然占据布局空间)
 [moonView addSymbolEffect:[NSSymbolDisappearEffect effect]];
 
 // 重新出现
 [moonView addSymbolEffect:[NSSymbolAppearEffect effect]];

CleanShot_2026-03-15_at_16.08.07.gif

3.5 出现 / 消失 —— 过渡行为(含完成回调)

过渡行为下,符号从视图层级真实移除,布局随之调整;可通过回调在动画结束后执行清理操作。

UIImageView *moonView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"moon.stars"]];
 
 [moonView addSymbolEffect:[NSSymbolDisappearEffect effect]
                  options:[NSSymbolEffectOptions options]
                 animated:YES
        completionHandler:^(NSSymbolEffectCompletionContext *context) {
     if (context.isFinished) {
         // 动画播放完毕,从父视图移除
         [context.sender removeFromSuperview];
     }
 }];

两个空间的核心区别

  • 无限行为 → 图像消失,视图仍在层级,布局不变
  • 过渡行为 → 从层级中真实移除,周围视图重新布局

3.6 不带动画地设置效果

在某些场景(如页面刚出现时需要立即呈现"已缩放"状态)可以关闭动画:

// animated: NO 跳过过渡动画,直接呈现目标状态
 [imageView addSymbolEffect:[NSSymbolDisappearEffect effect]
                   options:[NSSymbolEffectOptions options]
                   animated:NO];

3.7 Variable Value(变量值)动画

通过改变 variableValue 来驱动符号内部的层级渲染,适合信号强度、音量等连续变化场景。

// 创建带变量值的符号(0.0 ~ 1.0)
 UIImage *wifiImage = [UIImage systemImageNamed:@"wifi" variableValue:1.0 configuration:nil];
 UIImageView *imageView = [[UIImageView alloc] initWithImage:wifiImage];
 
 // 根据实时信号等级更新,系统自动插值动画
 - (void)updateSignalLevel:(double)level {
     UIImage *newImage = [UIImage systemImageNamed:@"wifi"
                                    variableValue:level
                                    configuration:nil];
     [self.signalImageView setSymbolImage:newImage
                        contentTransition:[NSSymbolAutomaticContentTransition transition]];
 }

3.8 UIBarButtonItem 也能加动画

工具栏按钮同样支持符号动画 API,让操作栏更有生命感:

UIBarButtonItem *downloadItem = [[UIBarButtonItem alloc]
    initWithImage:[UIImage systemImageNamed:@"arrow.down.circle"]
            style:UIBarButtonItemStylePlain
           target:self
           action:@selector(startDownload)];

// 添加无限脉冲动画表示下载进行中
[downloadItem addSymbolEffect:[NSSymbolPulseEffect effect]];

// 下载完成后移除
[downloadItem removeSymbolEffectOfType:[NSSymbolPulseEffect effect]];

4. 创建自定义动画符号

4.1 工作流概览

SF Symbols App 5 新增了动画查看器(Animation Viewer),可以在导出前预览并配置每种动画的行为。完整流程如下:

打开 SF Symbols App
  ↓
导入自定义 .svg 模板
  ↓
在 Animation Viewer 预览并选择动画效果
  ↓
添加图层注释(标记哪些图层参与动画)
  ↓
创建图层组(避免过度动画)
  ↓
选择目标平台与兼容性并导出
  ↓
将 .symbolset 拖入 Xcode Asset Catalog

CleanShot_2026-03-15_at_16.08.592x.png

4.2 图层组(Layer Groups)

默认情况下 SF Symbols 5 按图层运动,可能产生"零件四散"的奇怪效果。解决方案是将相关图层合并为图层组:

案例:魔方符号
✗ 按面分组 → 六个面各自弹跳,效果怪异
✓ 全部合并为一组 → 整个立方体一起弹跳,自然

原则:在同一视觉深度、属于同一语义单元的图层应归入同一图层组。


5. 符号组件(Symbol Components)

5.1 什么是符号组件

Apple 为常见的"修饰图案"提供了现成组件,包括:

组件 语义
Slash 禁用 / 关闭
Badge.plus 添加
Badge.minus 移除
Circle / Circle.fill 圆形外壳

设计一致性原则:系统内置符号大量复用这些模式。自定义符号采用相同组件,可让用户在第一眼就感到"熟悉"。

5.2 使用方法

在 SF Symbols App 中:

  1. 右键点击自定义符号 → 将一个符号与组件合并
  2. 从组件库选择(例如 Slash)
  3. 系统自动生成新符号并处理:
    • 正确的颜色注释
    • 独立的斜线动画
    • 多渲染模式适配(单色模式下自动变为擦除效果)

CleanShot_2026-03-15_at_16.11.57.gif

5.3 粗细补偿

符号组件内置可变模板支持(3 比例 × 9 粗细 = 27 种变体),系统会在符号尺寸缩小时自动加粗笔画,保证视觉重量与同尺寸的系统符号一致。

开发者可对极细体 / 黑体单独做微调(勾选 Override 后调整比例),中间粗细由系统自动插值。


6. 兼容性与导出

6.1 版本差异对照表

有一些动画虽然看上去很优美,但是一些版本中是不可以正常使用的

建议在实施动画之前要先做一层防爆,使用 @available 或版本判断即可

目标平台 SF Symbols 版本 特性
iOS 26+ / macOS Tahoe+ 7 Draw 动画、Variable Draw、渐变、增强 Magic Replace
iOS 17+ / macOS Sonoma+ 5 完整动画支持、图层组、线框导出
iOS 16 / macOS Ventura 4 可变颜色、多色渲染,但无动作
iOS 15 / macOS Monterey 3 可变模板,无动画优化绘图
iOS 14 / macOS Big Sur 2 静态模板,无可变模板

6.2 导出时的兼容性设置

SF Symbols App 导出对话框中:

  • 选择最新:生成带动画优化的完整绘图(线框视图)
  • 选择 SF Symbols 3:生成更简单的绘图,旧系统可正常显示静态符号
  • 选择 SF Symbols 2:生成静态模板,兼容最广

6.3 Objective-C 中的运行时版本判断

若需要在老系统上优雅降级(显示静态图标),使用 @available 或版本判断即可,符号动画 API 只在 iOS 17+ 可用:

if (@available(iOS 17.0, *)) {
    [imageView addSymbolEffect:[NSSymbolVariableColorEffect effect].iterative.reversing];
} else {
    // iOS 16 及以下:符号仍可正常显示,只是无动画
    imageView.image = [UIImage systemImageNamed:@"wifi.router"];
}

7. 最佳实践

7.1 优先使用 SF Symbols App 预览

在写代码前,先在 SF Symbols App 的 Animation Viewer 中预览效果,点击复制按钮可直接获取对应的 OC / Swift 代码片段,避免反复试错。

7.2 离散效果 vs 无限效果的选择

用户主动操作(点击、拖拽)→ 离散效果(Bounce、单次 Pulse)
系统后台状态(加载、连接)→ 无限效果(Variable Color、Scale)

7.3 叠加多个效果时注意层次

同一 ImageView 可叠加多个效果,但要避免视觉噪音:

// 合理叠加:可变颜色 + 轻微缩放,表示"正在激活"
[imageView addSymbolEffect:[NSSymbolVariableColorEffect effect].iterative];
[imageView addSymbolEffect:[NSSymbolScaleEffect effectScalingUp]];

// 不建议:叠加三种以上动画,视觉混乱

7.4 合理使用完成回调

过渡效果(Appear / Disappear)的完成回调适合处理:

  • 动画结束后将视图从父视图移除
  • 动画完成后触发下一步逻辑
[imageView addSymbolEffect:[NSSymbolDisappearEffect effect]
                  options:[NSSymbolEffectOptions options]
                  animated:YES
         completionHandler:^(NSSymbolEffectCompletionContext *context) {
    if (!context.isFinished) { return; } // 动画被中断,不处理
    // 清理逻辑
    [context.sender removeFromSuperview];
}];

7.5 UISlider 内置动画

iOS 17 的 UISlider 在拇指滑到轨道两端时会自动触发弹跳动画。如果你的 UI 不需要这个效果,可以关闭:

self.slider.isSymbolAnimationEnabled = NO; // Swift 属性,OC 同名

8. SF Symbols 7 新特性(WWDC 2025)

SF Symbols 7(随 iOS 26 / macOS Tahoe 推出)在动画和渲染层面带来了四项重要更新:Draw 动画、Variable Draw、Gradients(渐变)、以及增强的 Magic Replace。


8.1 Draw 动画(Draw On / Draw Off)

Draw 动画模拟手写笔画的有机流动,是 SF Symbols 7 最具表现力的新特性。符号从无到有(Draw On)或从有到无(Draw Off)地"描绘"自己。

三种播放模式

模式 说明 适用场景
byLayer(默认) 各路径交错启动,产生渐进感 复杂多层符号
wholeSymbol 所有层同时绘制,更简洁直接 简单符号、快速反馈
individually 逐层依次绘制,等上一层完成再启动下一层 强调意图的分步动画

绘制方向由系统决定

Apple 根据符号语义预设了绘制方向:

  • Wind 符号:从左到右(传达流动感)
  • 阿拉伯字符:从右到左(匹配书写方向)
  • 对称符号:从中心向两侧展开
  • 含箭头的路径:箭头随描绘路径移动,末端才"落点"

UIKit / Objective-C 代码

// Draw On — 符号从无到有
[imageView addSymbolEffect:[NSSymbolDrawEffect effectDrawingOn]];

// Draw Off — 符号从有到无,带完成回调后移除视图
[imageView addSymbolEffect:[NSSymbolDrawEffect effectDrawingOff]
                  options:[NSSymbolEffectOptions options]
                  animated:YES
         completionHandler:^(NSSymbolEffectCompletionContext *context) {
    if (context.isFinished) {
        [context.sender removeFromSuperview];
    }
}];

指定播放模式

// byLayer(默认,可省略)
[imageView addSymbolEffect:[[NSSymbolDrawEffect effectDrawingOn] byLayer]];

// wholeSymbol — 全符号同时绘制
[imageView addSymbolEffect:[[NSSymbolDrawEffect effectDrawingOn] wholeSymbol]];

// individually — 逐层依次绘制
[imageView addSymbolEffect:[[NSSymbolDrawEffect effectDrawingOn] individually]];

使用版本判断降级

if (@available(iOS 26.0, *)) {
    [imageView addSymbolEffect:[NSSymbolDrawEffect effectDrawingOn]];
} else {
    // iOS 25 及以下:使用 Appear 替代
    [imageView addSymbolEffect:[NSSymbolAppearEffect effect]];
}

8.2 Variable Draw(可变绘制)

Variable Draw 是一种新的渲染预设(非动画效果),通过路径的"已绘制比例"直观表达进度或强度。与 Variable Color 不同,它改变的是路径的填充长度而非颜色透明度。

典型场景:

  • 下载 / 上传进度条
  • 温度计刻度
  • 课程完成度
  • 音量渐变指示

与 Variable Color 的区别

特性 Variable Color Variable Draw
表达方式 图层透明度渐变 路径填充长度
视觉效果 颜色由深到浅 路径从头"画"到指定比例
适用场景 信号强度、激活状态 进度、强度

注意:同一符号可同时设计支持两种变量渲染,但运行时只能启用一种。使用 .default 让系统选择该符号首选的模式。

UIKit / Objective-C 代码

// 创建带变量值的图像,variableValue: 0.0 ~ 1.0
UIImage *thermometerImage = [UIImage systemImageNamed:@"thermometer.sun"
                                       variableValue:0.75
                                       configuration:nil];
UIImageView *imageView = [[UIImageView alloc] initWithImage:thermometerImage];

// 更新进度,系统自动使用 Variable Draw 插值
- (void)updateProgress:(double)progress {
    UIImage *newImage = [UIImage systemImageNamed:@"thermometer.sun"
                                   variableValue:progress
                                   configuration:nil];
    // 使用 automatic 内容过渡,让系统选择最佳方式
    [self.progressImageView setSymbolImage:newImage
                         contentTransition:[NSSymbolAutomaticContentTransition transition]];
}

指定使用 Variable Draw 模式(iOS 26+)

if (@available(iOS 26.0, *)) {
    // 显式指定渲染模式为 Draw(而非 Color)
    UIImageSymbolConfiguration *config =
        [UIImageSymbolConfiguration configurationWithVariableRenderingMode:UIImageSymbolVariableRenderingModeDraw];
    UIImage *image = [UIImage systemImageNamed:@"thermometer.sun"
                                variableValue:0.5
                                configuration:config];
    imageView.image = image;
}

8.3 Gradients(渐变)

SF Symbols 7 支持对符号应用线性渐变,单一源颜色即可生成有层次感的视觉效果,在较大尺寸时表现尤为突出。

特性:

  • 线性渐变,由单一颜色自动推导明暗
  • 支持所有渲染模式(Monochrome / Hierarchical / Palette / Multicolor)
  • 系统色和自定义色均可

UIKit / Objective-C 代码

// 单色渐变(Monochrome Gradient)
UIImageSymbolConfiguration *gradientConfig =
    [UIImageSymbolConfiguration configurationWithHierarchicalColor:[UIColor systemBlueColor]];
// iOS 26 新增渐变配置(示意,具体 API 以 Xcode 文档为准)
UIImage *gradientImage = [UIImage systemImageNamed:@"star.fill"
                                    withConfiguration:gradientConfig];
imageView.image = gradientImage;

提示:在 SF Symbols App 7 中,可以在画廊视图直接预览渐变效果,找到满意的配置后点击"复制代码"按钮获取 OC / Swift 代码片段。


8.4 Magic Replace 增强

Magic Replace 在 SF Symbols 5 时首次引入,负责识别两个相关符号并平滑切换(例如 play.fill → pause.fill)。SF Symbols 7 对其进行了两项增强:

增强 1:Enclosure Matching(封闭匹配)

系统识别两个符号是否共享相同的"外壳"(如圆形、方形边框),若匹配则保留外壳不动,仅替换内部图层。

符号 A               符号 B
[  play  ]    →    [  pause  ]
  ↑ 圆形外壳保持静止,内部图标用 Draw 动画替换

增强 2:自动集成 Draw 动画

新的 Magic Replace 会自动为替换过程加入 Draw 效果:

  • 离场符号:Draw Off
  • 入场符号:Draw On
// 无需额外配置,setSymbolImage:contentTransition: 自动使用增强版 Magic Replace
UIImage *pauseImage = [UIImage systemImageNamed:@"pause.circle.fill"];
[imageView setSymbolImage:pauseImage
        contentTransition:[NSSymbolAutomaticContentTransition transition]];
// 系统自动判断是否有匹配封闭 → 应用增强 Magic Replace

8.5 自定义符号的 Draw 注释(导航点)

要让自定义符号支持 Draw 动画,需要在 SF Symbols App 7 中为每条路径添加导航点(Guide Points),告诉系统绘制的起点、终点和路径走向

注意这一部分内容以文字形式讲解可能会有些问题,建议各位移步WWDC视频观看

导航点类型

类型 形状 作用
Start Point 空心圆 ○ 路径起始位置
End Point 实心圆 ● 路径结束位置
Guide Point 空心圆 ○ 路径转折点(紧转弯处必加)
Corner Point 菱形 ◇ 锐角转折

不同路径类型的注释策略

简单直线路径(如 line.diagonal****):

1. 放置起点(Start Point)
2. 放置终点(End Point)
→ 完成,系统自动绘制方向

多转折路径(如 scribble 涂鸦符号):

1. 在每个紧转折处额外放置 Guide Point
2. 保证路径平滑,避免绘制跳跃

多路径符号(如 line.3.horizontal 三横线):

- 为每条线独立注释
- 可为不同路径设置不同绘制方向
- 拖动起点越过已有导航点 → 方向自动反转

双向绘制(如 wave.3.up 波浪):

- 在路径中心放置起点
- 在两侧分别放置 Guide Point
- 系统识别为双向(显示两个箭头)
- 启用"对齐"确保各层起点对齐,保持对称

封闭路径(如 circle 圆形):

- 首个导航点自动同时作为 Start 和 End(显示胶囊形状 ◇)
- 默认顺时针绘制
- 右键 → 切换为逆时针

Attachment(附着)

对于箭头等"随路径移动但本身不是绘制对象"的元素,使用附着功能:

1. 将箭头图层拖动到已放置的导航点上
2. 箭头随该导航点沿路径移动
3. 要求箭头必须是独立路径(非混合形状)

Weight 权重插值规则

规则 说明
主注释权重 只能在 Regular 权重中添加/删除导航点
自动插值 Ultralight / Black 权重由系统自动插值
顺序一致性 各权重间导航点顺序必须相同,橙色标记 = 顺序错误
验证方式 开启"导航点编号"视图,逐一核对编号是否连续

Variable Draw 的自定义符号配置

在 SF Symbols App 7 中:

1. Settings → 启用 Variable Rendering
2. Layer List → 点击 Variable Draw 按钮
3. 仅勾选应展示进度的图层
   (例:温度计只勾选刻度层,外框保持完整显示)
4. 使用变量渲染滑块(0 ~ 100%)预览效果

附录:常用 Objective-C API 速查(更新至 SF Symbols 7)

操作 代码
添加无限效果 [iv addSymbolEffect:effect]
添加离散效果(N次) [iv addSymbolEffect:effect options:[NSSymbolEffectOptions optionsWithRepeatCount:N] animated:YES]
移除指定类型效果 [iv removeSymbolEffectOfType:effect]
内容过渡(替换) [iv setSymbolImage:img contentTransition:transition]
带完成回调的效果 [iv addSymbolEffect:effect options:opt animated:YES completionHandler:^(NSSymbolEffectCompletionContext *ctx){...}]
不带动画添加效果 [iv addSymbolEffect:effect options:opt animated:NO]
变量值图像 [UIImage systemImageNamed:@"wifi" variableValue:0.5 configuration:nil]
Draw On(iOS 26+) [iv addSymbolEffect:[NSSymbolDrawEffect effectDrawingOn]]
Draw Off(iOS 26+) [iv addSymbolEffect:[NSSymbolDrawEffect effectDrawingOff]]
Draw 整体播放 [[NSSymbolDrawEffect effectDrawingOn] wholeSymbol]
Draw 逐层播放 [[NSSymbolDrawEffect effectDrawingOn] individually]

引用资料

[1] WWDC23 Session 10258 — 在 App 中为符号添加动画效果
https://developer.apple.com/cn/videos/play/wwdc2023/10258

[2] WWDC23 Session 10257 — 创建带有动画效果的符号
https://developer.apple.com/cn/videos/play/wwdc2023/10257

[3] WWDC25 Session 337 — SF Symbols 7 新功能
https://developer.apple.com/videos/play/wwdc2025/337/

[4] WWDC23 Session 10197 — SF Symbols 5 的新功能
https://developer.apple.com/cn/videos/play/wwdc2023/10197

[5] SF Symbols App
https://developer.apple.com/sf-symbols/

[6] Apple 开发者文档 — NSSymbolEffect
https://developer.apple.com/documentation/symbols/nssymboleffect

[7] Apple 开发者文档 — UIImageView Symbol Effect APIs
https://developer.apple.com/documentation/uikit/uiimageview