Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2023 App ServicesDesignSwiftUI & UI Frameworks

WWDC23 · 17 min · App Services / Design / SwiftUI & UI Frameworks

Animate symbols in your app

Bring delight to your app with animated symbols. Explore the new Symbols framework, which features a unified API to create and configure symbol effects. Learn how SwiftUI, AppKit, and UIKit make it easy to animate symbols in user interfaces. Discover tips and tricks to seamlessly integrate the new animations alongside other app content. To get the most from this session, we recommend first watching “What’s new in SF Symbols 5.”

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 17 snippets

Symbol effects in SwiftUI swift · at 6:02 ↗
// Symbol effects in SwiftUI

Image(systemName: "wifi.router")
    .symbolEffect(.variableColor.iterative.reversing)
    .symbolEffect(.scale.up)
Symbol effects in AppKit and UIKit swift · at 6:02 ↗
let imageView: NSImageView = ...

imageView.addSymbolEffect(.variableColor.iterative.reversing)
imageView.addSymbolEffect(.scale.up)
Indefinite symbol effects in SwiftUI swift · at 6:49 ↗
struct ContentView: View {
    @State var isConnectingToInternet: Bool = true
    
    var body: some View {
        Image(systemName: "wifi.router")
            .symbolEffect(
                .variableColor.iterative.reversing,
                isActive: isConnectingToInternet
            )
    }
}
Indefinite symbol effects in AppKit and UIKit swift · at 7:09 ↗
let imageView: NSImageView = ...

imageView.addSymbolEffect(.variableColor.iterative.reversing)

// Later, remove the effect
imageView.removeSymbolEffect(ofType: .variableColor)
Discrete symbol effects in SwiftUI swift · at 8:26 ↗
struct ContentView: View {
    @State var bounceValue: Int = 0
    
    var body: some View {
        VStack {
            Image(systemName: "antenna.radiowaves.left.and.right")
                .symbolEffect(
                    .bounce,
                    options: .repeat(2),
                    value: bounceValue
                )
            
            Button("Animate") {
                bounceValue += 1
            }
        }
    }
}
Discrete symbol effects in AppKit and UIKit swift · at 8:26 ↗
let imageView: NSImageView = ...

// Bounce
imageView.addSymbolEffect(.bounce, options: .repeat(2))
Content transition symbol effects in SwiftUI swift · at 9:40 ↗
struct ContentView: View {
    @State var isPaused: Bool = false
    
    var body: some View {
        Button {
            isPaused.toggle()
        } label: {
            Image(systemName: isPaused ? "pause.fill" : "play.fill")
                .contentTransition(.symbolEffect(.replace.offUp))
        }
    }
}
Content transition symbol effects in AppKit and UIKit swift · at 9:57 ↗
let imageView: UIImageView = ...
imageView.image = UIImage(systemName: "play.fill")

// Change the image with a Replace effect
let pauseImage = UIImage(systemName: "pause.fill")!
imageView.setSymbolImage(pauseImage, contentTransition: .replace.offUp)
Indefinite Appear and Disappear symbol effects in SwiftUI swift · at 11:14 ↗
struct ContentView: View {
    @State var isMoonHidden: Bool = false
    
    var body: some View {
        HStack {
            RoundedRectangle(cornerRadius: 5)

            Image(systemName: "moon.stars")
               .symbolEffect(.disappear, isActive: isMoonHidden)

            Circle()
        }
    }
}
Indefinite Appear and Disappear symbol effects in AppKit and UIKit swift · at 11:30 ↗
let imageView: UIImageView = ...
imageView.image = UIImage(systemName: "moon.stars")

imageView.addSymbolEffect(.disappear)
// Re-appear the symbol
imageView.addSymbolEffect(.appear)
Transition symbol effects in SwiftUI swift · at 12:38 ↗
struct ContentView: View {
    @State var isMoonHidden: Bool = false
    
    var body: some View {
        HStack {
            RoundedRectangle(cornerRadius: 5)

            if !isMoonHidden {
                Image(systemName: "moon.stars")
                    .transition(.symbolEffect(.disappear.down))
            }

            Circle()
        }
    }
}
Appear and Disappear symbol effects in UIKit with completion handler swift · at 12:59 ↗
let imageView: UIImageView = ...
imageView.image = UIImage(systemName: "moon.stars")

imageView.addSymbolEffect(.disappear) { context in
    if let imageView = context.sender as? UIImageView, context.isFinished {
        imageView.removeFromSuperview()
    } 
}
Symbol effect propagation in SwiftUI swift · at 14:19 ↗
VStack {
    Image(systemName: "figure.walk")
        .symbolEffectsRemoved()
    Image(systemName: "car")
    Image(systemName: "tram")
}
.symbolEffect(.pulse)
Effects without animation in SwiftUI swift · at 14:55 ↗
struct ContentView: View {
    @State var isScaledUp: Bool = false
    
    var body: some View {
        Image(systemName: "iphone.radiowaves.left.and.right")
            .symbolEffect(.scale.up, isActive: isScaledUp)
            .onAppear {
                var transaction = Transaction()
                transaction.disablesAnimations = true
                withTransaction(transaction) {
                    isScaledUp = true
                }
            }
    }
}
Effects without animation in AppKit and UIKit swift · at 15:06 ↗
// Effects without animation in AppKit and UIKit

let imageView: UIImageView = ...
imageView.image = UIImage(systemName: "iphone.radiowaves.left.and.right")

imageView.addSymbolEffect(.disappear, animated: false)
Variable value animations in SwiftUI swift · at 15:44 ↗
struct ContentView: View {
    @State var signalLevel: Double = 0.5
    
    var body: some View {
        Image(systemName: "wifi", variableValue: signalLevel)
    }
}
Variable value animations in AppKit and UIKit swift · at 16:07 ↗
let imageView: UIImageView = ...
imageView.image = UIImage(systemName: "wifi", variableValue: 1.0)

// Animate to a different Wi-Fi level
let currentSignalImage = UIImage(
    systemName: "wifi",
    variableValue: signalLevel
)!
imageView.setSymbolImage(currentSignalImage, contentTransition: .automatic)