How do I animate a UIHostingController size with SwiftUI animations?

Generated on 8/5/2024

1 search

To animate a UIHostingController size with SwiftUI animations, you can leverage the new interoperability improvements between SwiftUI and UIKit. Specifically, you can use the new animate function on UIView and NSAnimationContext to bridge SwiftUI animations into UIKit.

Here's a step-by-step approach based on the information from the WWDC sessions:

  1. Use the animate Method: The animate method on the context allows you to apply any SwiftUI animation to the transaction associated with the update. This ensures that the animation runs in sync across both SwiftUI and UIKit views.

  2. Bridge the Animation: In your updateUIView method, you can grab the SwiftUI animation present on the transaction and bridge it to the UIView.animate method. This way, you can animate UIKit views using SwiftUI animations.

  3. Handle Transactions: If the current transaction isn't animated, the animation and completion are called immediately in line. This ensures that your code works whether the update is animated or not.

For a detailed explanation and example, you can refer to the session Enhance your UI animations and transitions (10:23).

Example Code

Here's a simplified example to illustrate the concept:

import SwiftUI
import UIKit

struct ContentView: View {
    @State private var isExpanded = false

    var body: some View {
        VStack {
            Button("Toggle Size") {
                withAnimation {
                    isExpanded.toggle()
                }
            }
            .padding()

            HostingControllerWrapper(isExpanded: $isExpanded)
                .frame(width: isExpanded ? 300 : 100, height: isExpanded ? 300 : 100)
                .animation(.spring(), value: isExpanded)
        }
    }
}

struct HostingControllerWrapper: UIViewControllerRepresentable {
    @Binding var isExpanded: Bool

    func makeUIViewController(context: Context) -> UIHostingController<InnerView> {
        return UIHostingController(rootView: InnerView())
    }

    func updateUIViewController(_ uiViewController: UIHostingController<InnerView>, context: Context) {
        let animation = context.transaction.animation
        UIView.animate(withDuration: animation?.duration ?? 0) {
            uiViewController.view.frame.size = CGSize(width: isExpanded ? 300 : 100, height: isExpanded ? 300 : 100)
        }
    }
}

struct InnerView: View {
    var body: some View {
        Color.blue
    }
}

In this example, the HostingControllerWrapper uses a UIViewControllerRepresentable to embed a SwiftUI view inside a UIKit view. The updateUIViewController method bridges the SwiftUI animation to UIKit using UIView.animate.

For more information on using animations across frameworks, you can also check out the session What’s new in SwiftUI (18:24).

Create custom hover effects in visionOS

Create custom hover effects in visionOS

Learn how to develop custom hover effects that update views when people look at them. Find out how to build an expanding button effect that combines opacity, scale, and clip effects. Discover best practices for creating effects that are comfortable and respect people’s accessibility needs.

What’s new in SwiftUI

What’s new in SwiftUI

Learn how you can use SwiftUI to build great apps for any Apple platform. Explore a fresh new look and feel for tabs and documents on iPadOS. Improve your window management with new windowing APIs, and gain more control over immersive spaces and volumes in your visionOS apps. We’ll also take you through other exciting refinements that help you make expressive charts, customize and layout text, and so much more.

What’s new in UIKit

What’s new in UIKit

Explore everything new in UIKit, including tab and document launch experiences, transitions, and text and input changes. We’ll also discuss better-than-ever interoperability between UIKit and SwiftUI animations and gestures, as well as general improvements throughout UIKit.

Enhance your UI animations and transitions

Enhance your UI animations and transitions

Explore how to adopt the zoom transition in navigation and presentations to increase the sense of continuity in your app, and learn how to animate UIKit views with SwiftUI animations to make it easier to build animations that feel continuous.

What’s new in AppKit

What’s new in AppKit

Discover the latest advances in Mac app development. Get an overview of the new features in macOS Sequoia, and how to adopt them in your app. Explore new ways to integrate your existing code with SwiftUI. Learn about the improvements made to numerous AppKit controls, like toolbars, menus, text input, and more.