在Mac应用中使用SwiftUI更改动画窗口大小

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Mac应用中使用SwiftUI更改动画窗口大小相关的知识,希望对你有一定的参考价值。

我正在为Mac应用程序使用SwiftUI,其中主窗口包含侧边栏视图和详细信息视图。选择侧边栏中的项目时,它将更改在详细视图中显示的视图。详细视图中显示的视图的大小不同,这会导致窗口的大小在显示时发生变化。但是,当窗口更改大小时,在更改大小的过程中看起来非常“刺眼”。有没有一种方法可以平滑地改变窗口大小的动画?

在详细视图中显示的视图:

// OneView.swift

struct OneView: View {
    var body: some View {
        VStack {
            Text("One View").font(.headline).padding()
            Text("Some stuff here.")
        }
        .frame(width: 400, height: 300)
    }
}

// TwoView.swift

struct TwoView: View {
    var body: some View {
        VStack {
            Text("Two View").font(.headline).padding()
            Text("More stuff is here.")
        }
        .frame(width: 400, height: 500)    }
}

// ThreeView.swift

struct ThreeView: View {
    var body: some View {
        VStack {
            Text("Three View").font(.headline).padding()
            Text("Another view goes here.")
        }
        .frame(width: 500, height: 200)
    }
}

主要内容视图,详细信息视图和侧边栏视图:

// ContentView.swift

struct SidebarView: View {

    @State private var selected = Set<String>()

    private let items = ["One View", "Two View", "Three View"]

    var body: some View {
        List(items, id: .self, selection: $selected) { item in
            NavigationLink(destination: DetailView(selection: item)) {
                Text("(item)")
            }
        }
        .listStyle(SidebarListStyle())
    }
}

struct DetailView: View {

    var selection: String

    var body: some View {
        switch selection {
        case "One View":
            return AnyView(OneView())
        case "Two View":
            return AnyView(TwoView())
        case "Three View":
            return AnyView(ThreeView())
        default:
            return AnyView(
                Text("Some (selection) view here").frame(maxWidth: .infinity, maxHeight: .infinity)
            )
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            SidebarView()
            DetailView(selection: "One View")
        }
    }
}
答案

这里是可行方法的演示。我是从另一种观点看的,因为您需要重新设计解决方案才能采用它。

演示

“

1)需要调整窗口大小的视图

struct ResizingView: View {
    public static let needsNewSize = Notification.Name("needsNewSize")

    @State var resizing = false
    var body: some View {
        VStack {
            Button(action: {
                self.resizing.toggle()
                NotificationCenter.default.post(name: Self.needsNewSize, object: 
                    CGSize(width: self.resizing ? 800 : 400, height: self.resizing ? 350 : 200))
            }, label: { Text("Resize") } )
        }
        .frame(minWidth: 400, maxWidth: .infinity, minHeight: 200, maxHeight: .infinity)
    }
}

2)窗口的所有者(在这种情况下为AppDelegate

import Cocoa
import SwiftUI
import Combine

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!
    var subscribers = Set<AnyCancellable>()

    func applicationDidFinishLaunching(_ aNotification: Notification) {

        let contentView = ResizingView()

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300), // just default
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        window.makeKeyAndOrderFront(nil)

        NotificationCenter.default.publisher(for: ResizingView.needsNewSize)
            .sink(receiveCompletion: {_ in}) { [unowned self] notificaiton in
                if let size = notificaiton.object as? CGSize {
                    var frame = self.window.frame
                    let old = self.window.contentRect(forFrameRect: frame).size

                    let dX = size.width - old.width
                    let dY = size.height - old.height

                    frame.origin.y -= dY // origin in flipped coordinates
                    frame.size.width += dX
                    frame.size.height += dY
                    self.window.setFrame(frame, display: true, animate: true)
                }
            }
            .store(in: &subscribers)
    }
    ...

以上是关于在Mac应用中使用SwiftUI更改动画窗口大小的主要内容,如果未能解决你的问题,请参考以下文章

如何向 swiftUI ScrollView 指示内容大小已更改?

Mac 上的 SwiftUI:关闭窗口并打开另一个窗口

如何在 SwiftUI mac 应用程序中更改屏幕背景颜色?

关闭窗口然后选择另一个应用程序时Mac应用程序消失

如何在 SwiftUI 中禁用子视图上的特定状态更改动画

SwiftUI 动画如何与子视图隔离?