Contents

pbalduz/swiftui-hosting-transitions

`SwiftUI` enables to perform smooth transitions between views using [`matchedGeometryEffect`](https://developer.apple.com/documentation/swiftui/view/matchedgeometryeffect(id:in:properties:anchor:issource:)) view modifier but what happens when the views are contained in `UIHosting

Installation

If you want to use Matched Transitions in an SPM project, just add it to the dependencies in your Package.swift:

dependencies: [
  .package(url: https://github.com/pbalduz/swiftui-hosting-transitions, from: "0.1.0")
]

Then, you can include in any target as a dependency:

targets: [
  .target(
    name: "MyTarget",
    dependencies: [
      .product(name: "MatchedTransitions", package, "swiftui-hosting-transitions")
    ]
]

You can also add it to and Xcode project by adding it as a package dependency.

Usage

The API to perform custom transitions is pretty simple and requires of two steps, identifying the SwiftUI views that should animate (source and destination) and wrapping the views' in a MatchedHostingController.

This is how the views to animate are identified:

struct FirstView: View {
  var body: some View {
    Color.red
      .frame(width: 100, height: 100)
      .matchedGeometry(id: "id", isSource: true)
  }
}

struct FirstView: View {
  var body: some View {
    Color.red
      .frame(maxWidth: .infinity)
      .frame(height: 100)
      .matchedGeometry(id: "id", isSource: false)
  }
}

Then we would just need to wrap the views in MatchedHostingControllers instead of UIHostingController:

class FirstViewController: MatchedHostingController<FirstView> {
  let state = MatchedGeometryState()
  
  init() {
    super.init(
      rootView: FirstView(),
      state: state
    )
  }
}

class SecondViewController: MatchedHostingController<SecondView> {
  init(state: MatchedGeometryState) {
    super.init(
      rootView: SecondView(),
      state: state
    )
  }
}

MatchedHostingController inherits from UIHostingController and retains a similar initialization API, with the addition of a state property crucial for the proper execution of transitions. It is essential to retain an instance of this property, as it must be passed to the destination view controller to enable the sharing of information about matched views.

Finally, in order to navigate between view controllers the regular navigation controller API can be used:

// from FirstViewController
let vc = SecondViewController(state: state)
navigationController?.pushViewController(vc, animated: true)

Demo

[matched-transition-demo]

What's next

  • Currently, only push navigation is supported and modal presentation is still to be implemented.
  • Interactive transitions?
  • MacOS navigation support?
  • Background transition for non matched views has a small weird opacity change when background is not white that should be addressed.

Package Metadata

Repository: pbalduz/swiftui-hosting-transitions

Default branch: main

README: README.md