There is nice api from apple to showing a view as sheet in macOS and sheet respect the size of sheetView even the size could be bigger than parent and it shows the sheetView nicely under the titlebar of parent view, and if we move the parent title, the child or the sheetView moves and follows the parent, so far so good. I am very interstate to build a diy codes which it's results would be same as apple sheet view in native macOS SwiftUI, so I could successfully show the childView but the childView or my custom sheetView position is completely independent from the parent view, looking to solve the position of childView that stand under parent menu title.
ps: I noticed if i remove the unneeded parameter from my function called sender: Any?
the window is not going show, how ever if I keep the unneeded parameter of sender: Any?
in function and also feeding it with nil
, it makes the child view show and work, not sure why that makes so big deal, but I wanted point it for you. May my codes need refactor and remove extra or unneeded part as well.
So my goal is to replicate apple sheet view and trying to solve the position issue of my childView to lock to parent view.
struct ContentView: View {
@State private var show: Bool = false
var body: some View {
Color.gray
.overlay(VStack {
Button("show sheet") { show.toggle() }
Button("show window") { sheetView().openInWindow(sender: nil) }
})
.frame(width: 200, height: 200)
.sheet(isPresented: $show, content: { sheetView() })
}
func sheetView() -> some View {
return Color.yellow
.frame(width: 400, height: 400)
}
}
extension View {
@discardableResult
func openInWindow(sender: Any?) -> NSWindow {
let controller = NSHostingController(rootView: self)
let window = NSWindow(contentViewController: controller)
window.contentViewController = controller
window.makeKeyAndOrderFront(sender)
window.titleVisibility = .hidden
window.toolbar = nil
window.styleMask = .fullSizeContentView
return window
}
}
CodePudding user response:
You just need to add it as a child to parent window, like
Button("show window") {
if let parent = NSApp.mainWindow {
let window = sheetView().openInWindow(sender: nil)
parent.addChildWindow(window, ordered: .above) // << here !!
}
}
and some animation (Tested with Xcode 13.4 / macOS 12.5)
Main part (macOS Y zero is at right-bottom):
var frame = parent.frame
let (midX, maxY) = (frame.midX, frame.maxY)
frame.size = window.frame.size
frame.origin = NSPoint(x: midX - frame.size.width/2, y: maxY - frame.size.height / 2.0)
window.setFrame(frame, display: true, animate: false)
window.makeKeyAndOrderFront(nil)
frame.size = window.frame.size
frame.origin = NSPoint(x: midX - frame.size.width/2, y: maxY - frame.size.height - 28)
window.setFrame(frame, display: true, animate: true)