swift - How can I detect when view resizing is finished? - Stack Overflow

I want to create a solution that tells me when the user has finished resizing a view. Currently, I’m us

I want to create a solution that tells me when the user has finished resizing a view. Currently, I’m using a timer for this, but I’m not satisfied with my approach because it doesn’t feel like idiomatic SwiftUI coding. I’m looking for a more native way to detect the final size of the view at the end of resizing. As we change the window size our view size would change.

import SwiftUI

struct ContentView: View {
    
    @State private var resizeTimer: Timer? = nil
    
    var body: some View {
        GeometryReader { geometryValue in
            Color.white
                .onChange(of: geometryValue.size) { newValue in

                    // Invalidate any existing timer
                    resizeTimer?.invalidate()

                    // Start a new timer to detect when resizing ends
                    resizeTimer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: false) {  _ in // [weak self]
                        didEndResizing(size: newValue)
                    }
                }
        }
        .padding()
    }
    
    private func didEndResizing(size: CGSize) {
        print("View resizing ended. Final size: \(size)")
    }
}

I want to create a solution that tells me when the user has finished resizing a view. Currently, I’m using a timer for this, but I’m not satisfied with my approach because it doesn’t feel like idiomatic SwiftUI coding. I’m looking for a more native way to detect the final size of the view at the end of resizing. As we change the window size our view size would change.

import SwiftUI

struct ContentView: View {
    
    @State private var resizeTimer: Timer? = nil
    
    var body: some View {
        GeometryReader { geometryValue in
            Color.white
                .onChange(of: geometryValue.size) { newValue in

                    // Invalidate any existing timer
                    resizeTimer?.invalidate()

                    // Start a new timer to detect when resizing ends
                    resizeTimer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: false) {  _ in // [weak self]
                        didEndResizing(size: newValue)
                    }
                }
        }
        .padding()
    }
    
    private func didEndResizing(size: CGSize) {
        print("View resizing ended. Final size: \(size)")
    }
}
Share Improve this question edited Nov 16, 2024 at 21:20 swiftPunk asked Nov 16, 2024 at 16:52 swiftPunkswiftPunk 1 4
  • How would the user resize the view? Views in general cannot be resized by the user unless you deliberately provide a mechanism for resizing it. Do you mean the window instead? – Sweeper Commented Nov 16, 2024 at 16:59
  • @swiftPunk How is a view supposed to know intrinsically when a size change is finished if the input for the change comes from external events like user inputs? Maybe I don't understand your question and you mean that you give a view a target size from the outside and the size of your view changes several times on the way to this target size? – ITGuy Commented Nov 16, 2024 at 19:12
  • @Sweeper: window, as we change the window size our view size would change. – swiftPunk Commented Nov 16, 2024 at 20:59
  • 1 @LeoDabus I disagree with the duplicate closure. The first reason is that the duplicate target is using AppKit and this question is about SwiftUI. While you can use the same approach as the answer in the duplicate target to solve this in SwiftUI, there might be other SwiftUI-specific ways (perhaps in the future). The second reason is that for a SwiftUI app with multiple windows, the didEndLiveResizeNotification approach also involves getting the current NSWindow, which is not trivial to do. – Sweeper Commented Nov 19, 2024 at 19:05
Add a comment  | 

1 Answer 1

Reset to default 1

To detect the end of a window resizing session, you can observe the NSWindow.didEndLiveResizeNotification.

.onReceive(NotificationCenter.default.publisher(for: NSWindow.didEndLiveResizeNotification)) { notification in
    print("Resize did end!")
}

notification.object tells you which NSWindow it is that got resized, so if your app has multiple windows, you can check that to respond only to resizes of the view's own window. For example:

struct ContentView: View {
    @State private var myWindow: NSWindow?
    var body: some View {
        Color.blue
            .background { WindowAccessor(window: $myWindow) }
            .onReceive(NotificationCenter.default.publisher(for: NSWindow.didEndLiveResizeNotification)) { notification in
                if (notification.object as? NSWindow) == myWindow {
                    print("Did resize!")
                }
            }
    }
}

struct WindowAccessor: NSViewRepresentable {
    @Binding var window: NSWindow?
    
    class MoveToWindowDetector: NSView {
        var onMoveToWindow: (NSWindow?) -> Void = { _ in }
        
        override func viewDidMoveToWindow() {
            onMoveToWindow(window)
        }
    }

    func makeNSView(context: Context) -> MoveToWindowDetector {
        MoveToWindowDetector()
    }

    func updateNSView(_ nsView: MoveToWindowDetector, context: Context) {
        nsView.onMoveToWindow = { window = $0 }
    }
}

WindowAccessor is slightly modified from Asperi's answer here.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745650670a4638245.html

相关推荐

  • swift - How can I detect when view resizing is finished? - Stack Overflow

    I want to create a solution that tells me when the user has finished resizing a view. Currently, I’m us

    22天前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信