我想要做一个视差背景视图,在那里,用户界面后面的图像几乎保持不变,因为窗口在屏幕上移动。要在macOS上这样做,我想要得到窗口的坐标。如何获得窗口的坐标?
我问这个是因为我找不到任何地方说该怎么做:
- [SwiftUI window coordinates](https://www.google.com/search?q=SwiftUI+window+coordinates), [SwiftUI window location](https://www.google.com/search?q=SwiftUI+window+location), [SwiftUI window get frame](https://www.google.com/search?q=SwiftUI+window+get+frame), [SwiftUI get window](https://www.google.com/search?q=SwiftUI+get+window), [SwiftUI macOS window coordinates](https://www.google.com/search?q=SwiftUI+macOS+window+coordinates), [SwiftUI macOS window location](https://www.google.com/search?q=SwiftUI+macOS+window+location), [SwiftUI macOS window get frame](https://www.google.com/search?q=SwiftUI+macOS+window+get+frame), [SwiftUI macOS get window](https://www.google.com/search?q=SwiftUI+macOS+get+window)
- [`GeometryReader`](https://developer.apple.com/documentation/swiftui/geometryreader) - I had hoped that this would contain an API to give me the frame in system coordinate space, but it seems all the approaches it contains only reference within-the-window coordinates
- [Creating a macOS App — SwiftUI Tutorials](https://developer.apple.com/tutorials/swiftui/creating-a-macos-app) - I was hoping Apple would have mentioned windowing in this, but it's not mentioned at all, aside from saying that you can preview the main window's contents in an Xcode preview pane
- Fruitless searches: [SwiftUI window coordinates](https://developer.apple.com/search/?q=SwiftUI%20window%20coordinates), [SwiftUI window location](https://developer.apple.com/search/?q=SwiftUI%20window%20location), [SwiftUI window get frame](https://developer.apple.com/search/?q=SwiftUI%20window%20get%20frame)
- [How to access own window within SwiftUI view?](https://stackoverflow.com/q/60359808/3939277) - I was optimistic that this would have an answer which would give me a SwiftUI API to access the window, but instead it uses a shim to access the AppKit window representation.
- [Define macOS window size using SwiftUI](https://stackoverflow.com/q/56857782/3939277) - Similar hopes as the above question, but this time the answer was just to read the frame of the content view, which again, always has a `(0, 0)` origin
- [SwiftUI coordinate space](https://stackoverflow.com/q/56443486/3939277) - I was hoping this answer would let me know how to transform the coordinates given by `GeometryReader` into screen coordinates, but unfortunately the coordinates are again constrained to within the window
- [SwiftUI for Mac - Part 2](https://troz.net/post/2019/swiftui-for-mac-2/) by [TrozWare](https://troz.net/) - I was hoping that this would give me some tips for using SwiftUI on Mac, such as interacting with windows, since most tutorials focus on iOS/iPadOS. Unfortunately, although it has lots of good information about how SwiftUI works with windows, it has no information on interacting with nor parsing those windows, themselves
- [SwiftUI Layout System](https://kean.github.io/post/swiftui-layout-system) by [Alexander Grebenyuk](https://kean.github.io/) - Was hoping for window layout within the screen, but this is all for full-screen iOS apps
- [SwiftUI by Example](https://www.hackingwithswift.com/quick-start/swiftui) by [Hacking with Swift](https://www.hackingwithswift.com/) - Was hoping for an example for how to get the position of a window, but it seems windows aren't really mentioned at all in the listed examples
正如我所列出的,我发现所有这些都与我的问题无关,或者只是引用窗口内的坐标,而不是引用屏幕中的窗口坐标。有些人提到了使用AppKit的方法,但如果可能的话,我想避免这种情况。
我得到的最接近的是试图使用这样的GeometryReader:
GeometryReader { geometry in
Text(verbatim: "\(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不是真实的,它没有指向EnvironmentValues上的任何键盘。我找不到我能从哪里得到这样的价值。
发布于 2022-06-19 12:14:37
到目前为止,我们已经广泛部署/安装了macOS 12,而SwiftUI还没有为macOS窗口获得一个合适的模型。根据我到目前为止对macOS 13的了解,窗口也不会有一个SwiftUI模型。
今天(自macOS 11以来),我们不再打开AppDelegate中的窗口,而是使用WindowGroup场景修饰符定义窗口:
@main
struct HandleWindowApp: App {
var body: some Scene {
WindowGroup(id: "main") {
ContentView()
}
}
}但是没有控制或访问底层窗口的标准方法(例如NSWindow)。要做到这一点,堆栈溢出上的多个答案建议使用一个WindowAccessor,它在ContentView的后台安装一个NSView,然后访问它的window属性。我还写了我的版本控制窗口的放置。在您的示例中,只需获得NSWindow实例的句柄,然后观察NSWindow.didMoveNotification即可。每当窗口移动时,它就会被调用。
如果您的应用程序只使用一个窗口(例如,您以某种方式阻止用户创建多个窗口),您甚至可以在全球范围内观察到帧的位置:
NotificationCenter.default
.addObserver(forName: NSWindow.didMoveNotification, object: nil, queue: nil) { (notification) in
if let window = notification.object as? NSWindow,
type(of: window).description() == "SwiftUI.SwiftUIWindow"
{
print(window.frame)
}
}发布于 2020-06-08 03:02:44
如果你想要窗框:
SceneDelegate跟踪所有窗口,因此您可以使用它生成一个引用其框架的EnvironmentObject,并将其传递给您的视图。更新委托方法中的环境对象值:func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, ...
如果它是一个窗口应用程序,那么它就更直接了。您可以在视图中使用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
}
}struct ContentView: View {
@EnvironmentObject var windowInfo: WindowInfo
var body: some View {
Group {
Text("Hello, World! \(windowInfo.frame.debugDescription)")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}https://stackoverflow.com/questions/62252446
复制相似问题