I have the following code:
import UIKit
import SwiftUI
class ViewController: UIViewController {
@IBOutlet weak var testButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBOutlet weak var swiftuiButton: UIButton!
@IBAction func didTap(_ sender: Any) {
let storyboard = UIStoryboard(name: "DetailsVC", bundle: .main)
let vc = storyboard.instantiateInitialViewController() as! DetailsVC
vc.modalPresentationStyle = .custom
vc.transitioningDelegate = self
present(vc, animated: true)
}
@IBAction func swiftUITest(_ sender: Any) {
let swiftUIView = SwiftUIView() {
self.dismiss(animated: true)
}
let hostingController = UIHostingController.init(rootView: swiftUIView)
hostingController.modalPresentationStyle = .custom
hostingController.transitioningDelegate = self
present(hostingController, animated: true)
}
}
struct SwiftUIView: View {
var didTapClose:()->()
var body: some View {
GeometryReader { geo in
ZStack {
Color.yellow.ignoresSafeArea()
Text("SWIFTUI VIEW")
.foregroundColor(.black)
}
.transaction { transaction in
transaction.animation = nil
}
.frame(width: geo.size.width, height: geo.size.height)
.border(.red)
.onTapGesture {
didTapClose()
}
}
}
}
extension ViewController:UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return ToTileDetailsAnimator(fromFrame: testButton.frame, duration: 5)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil
}
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return nil
}
}
final class ToTileDetailsAnimator:NSObject, UIViewControllerAnimatedTransitioning {
fileprivate(set) var fromFrame:CGRect
fileprivate(set) var duration:Double
init(fromFrame:CGRect, duration:Double) {
self.fromFrame = fromFrame
self.duration = duration
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromVC = transitionContext.viewController(forKey: .from) else { return }
let finalFrame = fromVC.view.frame.insetBy(dx: 20, dy: 20)
guard let toVC = transitionContext.viewController(forKey: .to) else { return }
let containerView = transitionContext.containerView
containerView.addSubview(toVC.view)
toVC.view.frame = fromFrame
toVC.view.clipsToBounds = true
toVC.view.layer.cornerRadius = 6
toVC.view.layoutIfNeeded()
fromVC.beginAppearanceTransition(false, animated: true)
toVC.beginAppearanceTransition(true, animated: true)
toVC.view.alpha = 0
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseInOut, animations: {
toVC.view.frame = finalFrame
toVC.view.alpha = 1
toVC.view.layoutIfNeeded()
}) { (completed) in
toVC.view.frame = finalFrame
toVC.view.layoutIfNeeded()
toVC.view.alpha = 1
fromVC.endAppearanceTransition()
toVC.endAppearanceTransition()
let transitionSuccess = !transitionContext.transitionWasCancelled
transitionContext.completeTransition(transitionSuccess)
}
}
}
Issue:
When presenting a UIViewController all works great. When presenting a UIHostingController the transition animation shows the SwiftUIView
NOT growing and like the UIKit case correctly does.
Why is the SwiftUIView not scaling up during the animation? Why is it at full size immediately?
This is what the transition animations look like: