我有一个带有自定义圆形的 MacOS 菜单栏应用程序
NSWindow
:
class RoundedWindow: NSWindow {
override var contentView: NSView? {
didSet {
guard let contentView = contentView else { return }
contentView.wantsLayer = true
contentView.layer?.cornerRadius = 10
contentView.layer?.masksToBounds = true
}
}
}
class ClearBackgroundHostingController<Content>: NSHostingController<Content> where Content: View {
override func loadView() {
self.view = NSView()
self.view.wantsLayer = true
self.view.layer?.backgroundColor = NSColor.clear.cgColor
}
}
还有我的
AppDelegate
中调整窗口大小的功能
func adjustWindowSize(to size: CGSize) {
guard let window = windowController.window else { return }
var newFrame = window.frame
newFrame.size = size
// Calculate the new Y position to keep the window top aligned.
let newY = window.frame.maxY - size.height
newFrame.origin.y = newY
NSAnimationContext.runAnimationGroup({ context in
context.duration = 10.0
context.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
window.animator().setFrame(newFrame, display: true)
}, completionHandler: nil)
}
我正在跟踪首选项窗口是否打开,并尝试相应地更新尺寸过渡并设置动画:
static let largeSize = CGSize(width: 512, height: 288)
static let smallSize = CGSize(width: 220, height: 220)
@State var size: CGSize = Self.smallSize
var body: some View {
ZStack {
if appDelegate.showingPreferences {
PreferencesView(appDelegate: appDelegate)
} else {
if viewModel.isVPNAvailable || !viewModel.isVPNAvailable {
mainContentView
}
if !viewModel.isVPNAvailable {
vpnNotAvailableView
}
}
}
.onChange(of: appDelegate.showingPreferences) { _ in
withAnimation(.easeInOut(duration: 1)) {
let newSize = size == Self.largeSize ? Self.smallSize : Self.largeSize
size = newSize
appDelegate.adjustWindowSize(to: newSize)
}
}
.onReceive(appDelegate.vpnStatusPublisher.receive(on: DispatchQueue.main)) { newStatus in
actionInProgress = false
switch newStatus {
case .connected:
appDelegate.vpnIsConnected = true
case .connecting, .disconnecting, .disconnected:
appDelegate.vpnIsConnected = false
}
}
.onChange(of: appDelegate.showingPreferences) { _ in
withAnimation(.easeInOut(duration: 1)) { // Adjust duration as needed
size = size == Self.largeSize ? Self.smallSize : Self.largeSize
}
}
}
为了匹配这个CodePen动画:https://codepen.io/formfield/pen/zYeJzXz
但是,我似乎实际上无法让任何动画发生。我以正确的方式处理这个问题吗?
我不知道您是否已经找到解决方案,但我认为错误在于您如何为框架设置动画。
窗框可以使用动画
window.setFrame(newFrame, display: true, animate: withAnimation)
(https://developer.apple.com/documentation/appkit/nswindow/1419519-setframe)
不幸的是,它的动画行为无法使用
NSAnimationContext.runAnimationGroup
进行调整。要调整持续时间,您可以使用: