为 Swift 5 更新
我总是发现以screen.frame 居中窗口会导致一个窗口感觉好像它离屏幕底部太近了。这是因为 Dock 的大小几乎是状态/菜单栏的 3 倍(分别约为 70-80 像素和 25 像素)。
这会导致窗口出现就好像它位于屏幕底部的下方,因为我们的眼睛不会自动调整状态栏(1x 大小)和 Dock ( ~3x 大小)。
出于这个原因,我总是选择使用screen.visibleFrame,因为它确实感觉更加居中。 visibleFrame 会同时考虑状态栏和 Dock 大小,并计算这两个对象之间框架的中心点。
extension NSWindow {
/// Positions the `NSWindow` at the horizontal-vertical center of the `visibleFrame` (takes Status Bar and Dock sizes into account)
public func positionCenter() {
if let screenSize = screen?.visibleFrame.size {
self.setFrameOrigin(NSPoint(x: (screenSize.width-frame.size.width)/2, y: (screenSize.height-frame.size.height)/2))
}
}
/// Centers the window within the `visibleFrame`, and sizes it with the width-by-height dimensions provided.
public func setCenterFrame(width: Int, height: Int) {
if let screenSize = screen?.visibleFrame.size {
let x = (screenSize.width-frame.size.width)/2
let y = (screenSize.height-frame.size.height)/2
self.setFrame(NSRect(x: x, y: y, width: CGFloat(width), height: CGFloat(height)), display: true)
}
}
/// Returns the center x-point of the `screen.visibleFrame` (the frame between the Status Bar and Dock).
/// Falls back on `screen.frame` when `.visibleFrame` is unavailable (includes Status Bar and Dock).
public func xCenter() -> CGFloat {
if let screenSize = screen?.visibleFrame.size { return (screenSize.width-frame.size.width)/2 }
if let screenSize = screen?.frame.size { return (screenSize.width-frame.size.width)/2 }
return CGFloat(0)
}
/// Returns the center y-point of the `screen.visibleFrame` (the frame between the Status Bar and Dock).
/// Falls back on `screen.frame` when `.visibleFrame` is unavailable (includes Status Bar and Dock).
public func yCenter() -> CGFloat {
if let screenSize = screen?.visibleFrame.size { return (screenSize.height-frame.size.height)/2 }
if let screenSize = screen?.frame.size { return (screenSize.height-frame.size.height)/2 }
return CGFloat(0)
}
}
用法
NSWindow
将现有窗口定位到 visibleFrame 的中心。
window!.positionCenter()
在 visibleFrame 的中心设置一个新的窗口框架,带有尺寸
window!.setCenterFrame(width: 900, height: 600)
NSView
使用xCenter() 和yCenter() 得到visibleFrame 的中心x-y 点。
let x = self.view.window?.xCenter() ?? CGFloat(0)
let y = self.view.window?.yCenter() ?? CGFloat(0)
self.view.window?.setFrame(NSRect(x: x, y: y, width: CGFloat(900), height: CGFloat(600)), display: true)
函数示例
override func viewDidLoad() {
super.viewDidLoad()
initWindowSize(width: 900, height: 600)
}
func initWindowSize(width: Int, height: Int) {
let x = self.view.window?.xCenter() ?? CGFloat(0)
let y = self.view.window?.yCenter() ?? CGFloat(0)
self.view.window?.setFrame(NSRect(x: x, y: y, width: CGFloat(width), height: CGFloat(height)), display: true)
}