admin管理员组文章数量:1026989
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
|
1 Answer
Reset to default 1To 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.
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 currentNSWindow
, which is not trivial to do. – Sweeper Commented Nov 19, 2024 at 19:05
1 Answer
Reset to default 1To 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.
本文标签: swiftHow can I detect when view resizing is finishedStack Overflow
版权声明:本文标题:swift - How can I detect when view resizing is finished? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745650669a2161299.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
didEndLiveResizeNotification
approach also involves getting the currentNSWindow
, which is not trivial to do. – Sweeper Commented Nov 19, 2024 at 19:05