NSScrollView 不滚动
NSScrollView not scrolling
我在 Mac 应用程序中有一个需要滚动的表单。我在 ViewController 中嵌入了一个 scrollView。我为 scrollView 分配了一个标识符,该标识符将它链接到它自己的 NSScrollView 文件。约束设置为视图控制器的顶部、右侧和左侧,它还将高度约束设置为 ViewController 的全高。
这是我的代码:
import Cocoa
class ScrollView: NSScrollView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
NSRect documentView.NSMakeSize(0, 0, 1058.width, 1232.height)
}
override func scrollWheel(with event: NSEvent) {
switch event.phase {
case NSEvent.Phase.began:
Swift.print("Began")
// case NSEvent.Phase.changed:
// Swift.print("Changed")
case NSEvent.Phase.ended:
Swift.print("Ended")
default:
break
}
switch event.momentumPhase {
case NSEvent.Phase.began:
Swift.print("Momentum Began")
// case NSEvent.Phase.changed:
// Swift.print("Momentum Changed")
case NSEvent.Phase.ended:
Swift.print("Momentum Ended")
default:
break
}
super.scrollWheel(with: event)
}
我似乎根本无法让我的应用程序滚动。我想我没有正确设置框架。正确设置框架的最佳方法是什么?我对 NSScrollView 的编码是否正确?
我认为你正在让你的生活变得非常艰难,因为你正在做一些 Apple 不完全推荐的事情。首先,你不应该继承NSScrollView
。相反,您应该首先阅读 Apple 的 Introduction to Scroll View Programming Guide for Cocoa 以了解您应该如何创建正确的视图层次结构以使 NSScrollView
正常工作。
第二个建议是让您查看此 nice article 关于您应该如何在游乐场中设置 NSScrollView
的内容,以便您可以使用您想要实现的代码。
第三,使用 Autolayout 和 NSScrollView
给很多人带来了很多痛苦。您需要正确设置 AutoLayout,以便一切都按预期工作。我建议您查看 Ken Thomases 的 ,它清楚地解释了您需要如何设置自动布局约束才能使 NSScrollView
正常工作。
我刚刚在 NSWindow 中使用 NSScrollView 克服了 "hump"。为了发生滚动,NSScrollview 中的视图需要大于内容 window。这很难用动态约束来设置。将内部视图静态设置为比 window "works" 更大的 width/height 但静态大小通常不是您想要的。
Here is my interface builder view hierarchy and constraints, not including the programmatically added boxes
在我的应用中,用户在 mainView 中添加 "boxes"(自定义可拖动视图),它位于 NSwindow.
的滚动视图中
这是我想要的功能:
如果我展开 NSWindow,我希望滚动视图中的 mainView 展开以填满整个 window。如果所有框都可见,则在这种情况下无需滚动。
如果我缩小 NSWindow,我希望滚动视图中的 mainView 缩小到足以包含我所有的 mainView 子视图("boxes"),但不会进一步缩小(我添加了一个 minBorder 20)。如果框的位置比 nswindow 的 width/height.
更远 right/up,这会导致滚动
我发现诀窍是根据每个可拖动框视图的最大角或 nswindow 的内容框架的 height/width 来计算我想要的 mainView 的大小,以哪个为准更大。
下面是我的代码,包括一些调试打印。
注意使用哪些子视图来计算最大尺寸。如果您包含一个动态附加到 window 的 right/top 的子视图,那么您的 window 将永远不会缩小。如果向其添加 +20 边框,则可能会无限循环。对我来说不是问题。
extension MapWindowController: NSWindowDelegate {
func windowDidEndLiveResize(_ notification: Notification) {
if let frame = window?.frame, let content = window?.contentRect(forFrameRect: frame) {
print("window did resize \(frame)")
var maxX: CGFloat = content.width
var maxY: CGFloat = content.height
for view in mainView?.subviews ?? [] {
let frameMaxX = view.frame.maxX + minBorder
let frameMaxY = view.frame.maxY + minBorder
if frameMaxX > maxX {
maxX = frameMaxX
}
if frameMaxY > maxY {
maxY = frameMaxY
}
}
print("view maxX \(maxX) maxY \(maxY)")
print("window width \(content.width) height \(content.height)")
mainView?.setFrameSize(NSSize(width: maxX, height: maxY))
}
}
}
我在 Mac 应用程序中有一个需要滚动的表单。我在 ViewController 中嵌入了一个 scrollView。我为 scrollView 分配了一个标识符,该标识符将它链接到它自己的 NSScrollView 文件。约束设置为视图控制器的顶部、右侧和左侧,它还将高度约束设置为 ViewController 的全高。
这是我的代码:
import Cocoa
class ScrollView: NSScrollView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
NSRect documentView.NSMakeSize(0, 0, 1058.width, 1232.height)
}
override func scrollWheel(with event: NSEvent) {
switch event.phase {
case NSEvent.Phase.began:
Swift.print("Began")
// case NSEvent.Phase.changed:
// Swift.print("Changed")
case NSEvent.Phase.ended:
Swift.print("Ended")
default:
break
}
switch event.momentumPhase {
case NSEvent.Phase.began:
Swift.print("Momentum Began")
// case NSEvent.Phase.changed:
// Swift.print("Momentum Changed")
case NSEvent.Phase.ended:
Swift.print("Momentum Ended")
default:
break
}
super.scrollWheel(with: event)
}
我似乎根本无法让我的应用程序滚动。我想我没有正确设置框架。正确设置框架的最佳方法是什么?我对 NSScrollView 的编码是否正确?
我认为你正在让你的生活变得非常艰难,因为你正在做一些 Apple 不完全推荐的事情。首先,你不应该继承NSScrollView
。相反,您应该首先阅读 Apple 的 Introduction to Scroll View Programming Guide for Cocoa 以了解您应该如何创建正确的视图层次结构以使 NSScrollView
正常工作。
第二个建议是让您查看此 nice article 关于您应该如何在游乐场中设置 NSScrollView
的内容,以便您可以使用您想要实现的代码。
第三,使用 Autolayout 和 NSScrollView
给很多人带来了很多痛苦。您需要正确设置 AutoLayout,以便一切都按预期工作。我建议您查看 Ken Thomases 的 NSScrollView
正常工作。
我刚刚在 NSWindow 中使用 NSScrollView 克服了 "hump"。为了发生滚动,NSScrollview 中的视图需要大于内容 window。这很难用动态约束来设置。将内部视图静态设置为比 window "works" 更大的 width/height 但静态大小通常不是您想要的。
Here is my interface builder view hierarchy and constraints, not including the programmatically added boxes
在我的应用中,用户在 mainView 中添加 "boxes"(自定义可拖动视图),它位于 NSwindow.
的滚动视图中这是我想要的功能:
如果我展开 NSWindow,我希望滚动视图中的 mainView 展开以填满整个 window。如果所有框都可见,则在这种情况下无需滚动。
如果我缩小 NSWindow,我希望滚动视图中的 mainView 缩小到足以包含我所有的 mainView 子视图("boxes"),但不会进一步缩小(我添加了一个 minBorder 20)。如果框的位置比 nswindow 的 width/height.
更远 right/up,这会导致滚动
我发现诀窍是根据每个可拖动框视图的最大角或 nswindow 的内容框架的 height/width 来计算我想要的 mainView 的大小,以哪个为准更大。
下面是我的代码,包括一些调试打印。
注意使用哪些子视图来计算最大尺寸。如果您包含一个动态附加到 window 的 right/top 的子视图,那么您的 window 将永远不会缩小。如果向其添加 +20 边框,则可能会无限循环。对我来说不是问题。
extension MapWindowController: NSWindowDelegate {
func windowDidEndLiveResize(_ notification: Notification) {
if let frame = window?.frame, let content = window?.contentRect(forFrameRect: frame) {
print("window did resize \(frame)")
var maxX: CGFloat = content.width
var maxY: CGFloat = content.height
for view in mainView?.subviews ?? [] {
let frameMaxX = view.frame.maxX + minBorder
let frameMaxY = view.frame.maxY + minBorder
if frameMaxX > maxX {
maxX = frameMaxX
}
if frameMaxY > maxY {
maxY = frameMaxY
}
}
print("view maxX \(maxX) maxY \(maxY)")
print("window width \(content.width) height \(content.height)")
mainView?.setFrameSize(NSSize(width: maxX, height: maxY))
}
}
}