I've been trying to create a sliding transition from one child view controller to another inside an NSPopover.
My problem is that the child view controllers do not stick to the top of the NSPopover during the transition. They animate in from the bottom or top:
Expected behaviour: both child view controllers should stick to the top during the transition and should simply slide over horizontally.
This is the function I wrote to trigger the transition:
func loadViewController(_ childViewController: NSViewController, withTransition transitionOptions: NSViewController.TransitionOptions?) {
addChild(childViewController)
view.addSubview(childViewController.view)
childViewController.view.layer?.borderColor = NSColor(calibratedRed: 0, green: 255, blue: 0, alpha: 1).cgColor
childViewController.view.layer?.borderWidth = 2
childViewController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
view.layout()
let oldViewController = currentViewController
currentViewController = childViewController
oldViewController?.view.layer?.borderColor = NSColor(calibratedRed: 255, green: 0, blue: 0, alpha: 1).cgColor
oldViewController?.view.layer?.borderWidth = 2
if let oldViewController = oldViewController {
transition(from: oldViewController, to: currentViewController!, options: transitionOptions ?? .slideLeft, completionHandler: { [weak oldViewController] in
oldViewController?.removeFromParent()
oldViewController?.view.removeFromSuperview()
})
}
NSAnimationContext.runAnimationGroup({ (context) -> Void in
context.duration = 0.5
context.allowsImplicitAnimation = true
self.parentPopover?.contentSize = NSSize(width: childViewController.preferredContentSize.width, height: childViewController.preferredContentSize.height)
})
}
Any idea what could be causing the issue? I've tried playing around with the constraints of both the child and parent view controllers as well as their frame sizes. I just can't figure out what I'm doing wrong.
I've uploaded the complete reproducible example here: https://github.com/maximilianschmitt/DebugPopoverAnimation
Thanks a lot for your help!
If you expect as on below animation
then just remove update of content size from animation block, as below
self.parentPopover?.contentSize = NSSize(width: childViewController.preferredContentSize.width, height: childViewController.preferredContentSize.height)
NSAnimationContext.runAnimationGroup({ (context) -> Void in
context.duration = 0.5
context.allowsImplicitAnimation = true
}) {
oldViewController?.removeFromParent()
oldViewController?.view.removeFromSuperview()
}
Update: keep popover content animatable (above changes are not needed)
For this case the only you need is to flip coordinate system for popover content view (which is a view of MasterViewController)
class PopoverContentView: NSView {
override var isFlipped: Bool { true }
}
class MasterViewController: NSViewController {
...
override func loadView() {
self.view = PopoverContentView()
}