Macos 如何在SwiftUI中获取窗口坐标?
我想制作一个视差背景视图,当窗口在屏幕上移动时,UI后面的图像几乎保持静止。要在macOS上执行此操作,我需要获取窗口的坐标如何获取窗口的坐标?Macos 如何在SwiftUI中获取窗口坐标?,macos,swiftui,Macos,Swiftui,我想制作一个视差背景视图,当窗口在屏幕上移动时,UI后面的图像几乎保持静止。要在macOS上执行此操作,我需要获取窗口的坐标如何获取窗口的坐标? 我这样问是因为我找不到任何地方说明如何做到这一点: 谷歌搜索帮助我找到以下结果: , 苹果开发者文档: -我曾希望这将包含一个API,以提供系统坐标空间中的框架,但似乎所有方法都只包含窗口坐标中的引用 -我本来希望苹果会在这篇文章中提到窗口,但除了说你可以在Xcode预览窗格中预览主窗口的内容之外,根本没有提到 无果搜索: 其他问题: -
我这样问是因为我找不到任何地方说明如何做到这一点:
- 谷歌搜索帮助我找到以下结果:
- ,
- 苹果开发者文档:
- -我曾希望这将包含一个API,以提供系统坐标空间中的框架,但似乎所有方法都只包含窗口坐标中的引用
- -我本来希望苹果会在这篇文章中提到窗口,但除了说你可以在Xcode预览窗格中预览主窗口的内容之外,根本没有提到
- 无果搜索:
- 其他问题:
- -我很乐观,这将有一个答案,它将为我提供一个快速UI API来访问窗口,但它使用一个垫片来访问AppKit窗口表示
- -与上述问题类似,但这一次的答案只是阅读内容视图的框架,该框架始终具有
原点(0,0)
- -我希望这个答案能让我知道如何将
给出的坐标转换为屏幕坐标,但不幸的是,坐标再次被限制在窗口内GeometryReader
- 网上其他地方:
- 顺便说一句,我希望这能给我一些在Mac上使用SwiftUI的技巧,比如与windows交互,因为大多数教程都关注iOS/iPadOS。不幸的是,尽管它有很多关于SwiftUI如何与windows协同工作的好信息,但它没有关于与这些窗口交互或解析这些窗口本身的信息
- by-希望在屏幕上显示窗口布局,但这是全屏幕iOS应用程序的全部
- by-希望能有一个示例来说明如何获取窗口的位置,但在列出的示例中似乎根本没有提到窗口
GeometryReader
如下:
public struct ParallaxBackground<Background: View>: View {
var background: Background
@Environment(\.windowFrame)
var windowFrame: CGRect
public var body: some View {
background
.offset(x: windowFrame.minX / 10,
y: windowFrame.minY / 10)
}
}
GeometryReader{geometry中的几何体
文本(逐字:\(geometry.frame(in:.global)))
}
但原点始终是(0,0)
,尽管在我调整窗口时大小确实发生了变化
我所设想的可能是这样的:
public struct ParallaxBackground<Background: View>: View {
var background: Background
@Environment(\.windowFrame)
var windowFrame: CGRect
public var body: some View {
background
.offset(x: windowFrame.minX / 10,
y: windowFrame.minY / 10)
}
}
公共结构视差背景:视图{
背景:背景
@环境(\.windowFrame)
var windowFrame:CGRect
公共机构:一些看法{
背景
.偏移量(x:windowFrame.minX/10,
y:windowFrame.minY/10)
}
}
但是窗框不是真的;它不指向
EnvironmentValues
上的任何键路径。我找不到在哪里可以得到这样的值。如果您想要窗框:
SceneDelegate跟踪所有窗口,因此您可以使用它创建一个EnvironmentObject
,并引用它们的帧,然后将其传递给视图。更新委托方法中的环境对象值:func-windowScene(windowScene:UIWindowScene,diddupdate-previouscoordinarespace:uicoordinarespace,…
如果它是一个单窗口应用程序,则更直接。您可以在视图中使用UIScreen.main.bounds(如果是全屏)或计算变量:
var frame:CGRect{(UIApplication.shared.connectedScenes.first?.delegate as?SceneDelegate)?.window?.frame???.zero}
但是,如果要在窗口中查找视图的框架,请尝试以下操作:
struct ContentView: View {
@State var frame: CGRect = .zero
var orientationChangedPublisher = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
var body: some View {
VStack {
Text("text frame georeader \(frame.debugDescription)")
}
.background(GeometryReader { geometry in
Color.clear // .edgesIgnoringSafeArea(.all) // may need depending
.onReceive(self.orientationChangedPublisher.removeDuplicates()) { _ in
self.frame = geometry.frame(in: .global)
}
})
}
}
尽管如此,通常你不需要一个绝对的框架。对齐向导让你相对地放置物体
//对于macOS应用程序,使用帧更改通知并作为环境对象传递到SwiftUI视图
class WindowInfo: ObservableObject {
@Published var frame: CGRect = .zero
}
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
let windowInfo = WindowInfo()
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
.environmentObject(windowInfo)
// Create the window and set the content view.
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView)
window.contentView?.postsFrameChangedNotifications = true
window.makeKeyAndOrderFront(nil)
NotificationCenter.default.addObserver(forName: NSView.frameDidChangeNotification, object: nil, queue: nil) { (notification) in
self.windowInfo.frame = self.window.frame
}
}
正如我在问题顶部及其标签中所说的,这是针对macOS应用程序的。虽然在iOS中考虑这一点很简单,但你能将其从UIKit转换为AppKit吗?我希望你可以用NSView.frameDidChangeNotification替换方向更改通知,但它不起作用。然而,在一个循环中,你仍然可以l使用它获取帧信息并将其传递给SwiftUI视图(更新的答案)。