水平和垂直嵌套滚动视图
Horizontal and vertical nested scroll views
我的视图包含一个水平滚动的滚动视图,其中包含多个垂直滚动的 Table 视图。
见图:
但是,Table 视图在光标位于滚动视图中时会阻止水平滚动。
如何让滚动条传递到超级视图?
申请代码
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
var viewController: ViewController!
func applicationDidFinishLaunching(aNotification: NSNotification) {
viewController = ViewController(nibName: "ViewController", bundle: nil)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
window.contentView!.addSubview(viewController.view)
//...
}
//...
}
视图控制器
class ViewController: NSViewController {
@IBOutlet weak var scrollView: NSScrollView!
//...
func addListView(listPath: String) {
let listView = ListViewController(nibName: "ListView", bundle: nil)
listView!.listPath = listPath
listView!.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.contentView.addSubview(listView!.view)
//...
}
//...
}
列表视图
class ListViewController: NSViewController {
@IBOutlet weak var itemsTitleView: NSTextField!
@IBOutlet weak var itemsTableView: MyTableView!
//...
}
Table查看
class MyTableView: NSTableView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
// Drawing code here.
}
var mainScrollView: NSScrollView? {
let app = NSApplication.sharedApplication()
let delegate = app.delegate as! AppDelegate
return delegate.viewController.scrollView
}
override func mouseDown(theEvent: NSEvent) {
// do nothing
}
override func scrollWheel(theEvent: NSEvent) {
if theEvent.scrollingDeltaY == 0 {
// It's a horizontal scroll -> redirect it
if let tableScrollView = enclosingScrollView, mainScrollView = mainScrollView {
mainScrollView.scrollWheel(theEvent)
}
} else {
// It's a vertical scroll -> behave normally
super.scrollWheel(theEvent)
}
}
}
我要尝试的第一件事是在滚动事件传递到 table 视图时捕获它。确定事件对象表示水平滚动手势后,将其重定向到主滚动视图。
class MyTableView: NSTableView {
var mainScrollView: NSScrollView? {
// Your tables will need some way to access the main scroll view.
// I'm assuming here that there's a reference to it on the AppDelegate
let app = NSApplication.sharedApplication()
let delegate = app.delegate as! AppDelegate
return delegate.mainScrollView
}
override func scrollWheel(theEvent: NSEvent) {
if theEvent.scrollingDeltaY == 0 {
// It's a horizontal scroll -> redirect it
if let tableScrollView = enclosingScrollView, mainScrollView = self.mainScrollView {
mainScrollView.scrollWheel(theEvent)
}
} else {
// It's a vertical scroll -> behave normally
super.scrollWheel(theEvent)
}
}
}
不过我不得不说,任何时候你开始搞乱这样的事件,你都需要为副作用做好准备;在我为测试这段代码而创建的简单演示应用程序中,它似乎工作正常,但如果这种方法引发了额外的挑战,请不要感到惊讶。
正如 Paul 指出的那样,使用他的方法可能会出现一些细微的问题 - 我在使用与他的回答非常相似的方法时看到了 NSTrackingArea 的问题。
查看 Jakob 对类似问题的回答以获得更可靠的方法:
NSScrollView inside another NSScrollView
我的视图包含一个水平滚动的滚动视图,其中包含多个垂直滚动的 Table 视图。
见图:
但是,Table 视图在光标位于滚动视图中时会阻止水平滚动。
如何让滚动条传递到超级视图?
申请代码
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
var viewController: ViewController!
func applicationDidFinishLaunching(aNotification: NSNotification) {
viewController = ViewController(nibName: "ViewController", bundle: nil)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
window.contentView!.addSubview(viewController.view)
//...
}
//...
}
视图控制器
class ViewController: NSViewController {
@IBOutlet weak var scrollView: NSScrollView!
//...
func addListView(listPath: String) {
let listView = ListViewController(nibName: "ListView", bundle: nil)
listView!.listPath = listPath
listView!.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.contentView.addSubview(listView!.view)
//...
}
//...
}
列表视图
class ListViewController: NSViewController {
@IBOutlet weak var itemsTitleView: NSTextField!
@IBOutlet weak var itemsTableView: MyTableView!
//...
}
Table查看
class MyTableView: NSTableView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
// Drawing code here.
}
var mainScrollView: NSScrollView? {
let app = NSApplication.sharedApplication()
let delegate = app.delegate as! AppDelegate
return delegate.viewController.scrollView
}
override func mouseDown(theEvent: NSEvent) {
// do nothing
}
override func scrollWheel(theEvent: NSEvent) {
if theEvent.scrollingDeltaY == 0 {
// It's a horizontal scroll -> redirect it
if let tableScrollView = enclosingScrollView, mainScrollView = mainScrollView {
mainScrollView.scrollWheel(theEvent)
}
} else {
// It's a vertical scroll -> behave normally
super.scrollWheel(theEvent)
}
}
}
我要尝试的第一件事是在滚动事件传递到 table 视图时捕获它。确定事件对象表示水平滚动手势后,将其重定向到主滚动视图。
class MyTableView: NSTableView {
var mainScrollView: NSScrollView? {
// Your tables will need some way to access the main scroll view.
// I'm assuming here that there's a reference to it on the AppDelegate
let app = NSApplication.sharedApplication()
let delegate = app.delegate as! AppDelegate
return delegate.mainScrollView
}
override func scrollWheel(theEvent: NSEvent) {
if theEvent.scrollingDeltaY == 0 {
// It's a horizontal scroll -> redirect it
if let tableScrollView = enclosingScrollView, mainScrollView = self.mainScrollView {
mainScrollView.scrollWheel(theEvent)
}
} else {
// It's a vertical scroll -> behave normally
super.scrollWheel(theEvent)
}
}
}
不过我不得不说,任何时候你开始搞乱这样的事件,你都需要为副作用做好准备;在我为测试这段代码而创建的简单演示应用程序中,它似乎工作正常,但如果这种方法引发了额外的挑战,请不要感到惊讶。
正如 Paul 指出的那样,使用他的方法可能会出现一些细微的问题 - 我在使用与他的回答非常相似的方法时看到了 NSTrackingArea 的问题。
查看 Jakob 对类似问题的回答以获得更可靠的方法:
NSScrollView inside another NSScrollView