相当多的关于以编程方式实现滚动视图的帖子,但我还没有找到适合这种情况的解决方案......在这里我将子视图添加到文档视图(所有内容都使用布局锚点布置),除了滚动。
我认为这里的问题是 AppKit 将示例中的约束解释为没有任何可滚动的内容,但我不知道为什么......
import Cocoa
class ViewController: NSViewController {
var scrollView = NSScrollView()
var contentView = NSClipView()
var documentView = ParentView()
var generateButton = NSButton()
@objc func generate(_ sender: NSObject) {
let child = ChildView()
child.translatesAutoresizingMaskIntoConstraints = false
documentView.addSubview(child)
documentView.setupChildViewLayout(sv: child)
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(generateButton)
view.addSubview(scrollView)
setupLayout()
}
func setupLayout() {
scrollView.contentView = contentView
scrollView.documentView = documentView
scrollView.borderType = .lineBorder
scrollView.hasHorizontalScroller = true
scrollView.hasVerticalScroller = true
scrollView.translatesAutoresizingMaskIntoConstraints = false
contentView.translatesAutoresizingMaskIntoConstraints = false
documentView.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints([
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10),
scrollView.trailingAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -150),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -100)
])
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10),
scrollView.trailingAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -150),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -100)
])
scrollView.addConstraints([
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.trailingAnchor.constraint(greaterThanOrEqualTo: scrollView.trailingAnchor),
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.bottomAnchor.constraint(greaterThanOrEqualTo: scrollView.bottomAnchor)
])
NSLayoutConstraint.activate([
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.trailingAnchor.constraint(greaterThanOrEqualTo: scrollView.trailingAnchor),
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.bottomAnchor.constraint(greaterThanOrEqualTo: scrollView.bottomAnchor)
])
scrollView.addConstraints([
documentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
documentView.trailingAnchor.constraint(greaterThanOrEqualTo: scrollView.trailingAnchor),
documentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
documentView.bottomAnchor.constraint(greaterThanOrEqualTo: scrollView.bottomAnchor)
])
NSLayoutConstraint.activate([
documentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
documentView.trailingAnchor.constraint(greaterThanOrEqualTo: scrollView.trailingAnchor),
documentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
documentView.bottomAnchor.constraint(greaterThanOrEqualTo: scrollView.bottomAnchor)
])
// Setup anchor constraints for the button
setupGenerateButton()
generateButton.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints([
generateButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10),
generateButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -30),
generateButton.heightAnchor.constraint(equalToConstant: 30),
generateButton.widthAnchor.constraint(equalToConstant: 200)
])
NSLayoutConstraint.activate([
generateButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10),
generateButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -30),
generateButton.heightAnchor.constraint(equalToConstant: 30),
generateButton.widthAnchor.constraint(equalToConstant: 200)
])
}
func setupGenerateButton() {
generateButton.attributedTitle = NSMutableAttributedString(string: "GenerateChildView", attributes: [NSAttributedString.Key.strokeColor: (NSColor.white), NSAttributedString.Key.font: NSFont.systemFont(ofSize: (NSFont.systemFontSize))])
generateButton.wantsLayer = true
generateButton.bezelColor = NSColor(red: 0.2, green: 0.2, blue: 0.6, alpha: 1.0)
generateButton.action = #selector(self.generate(_:))
}
}
class ParentView: NSView {
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
}
func setupChildViewLayout(sv: ChildView) {
if (self.subviews.count < 2) {
self.addConstraints([
sv.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor),
sv.topAnchor.constraint(equalTo: self.topAnchor)
])
NSLayoutConstraint.activate([
sv.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor),
sv.topAnchor.constraint(equalTo: self.topAnchor)
])
}
else {
let c = self.subviews.count - 2
let lastView = self.subviews[c]
self.addConstraints([
sv.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor),
sv.topAnchor.constraint(equalTo: lastView.bottomAnchor)
])
NSLayoutConstraint.activate([
sv.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor),
sv.topAnchor.constraint(equalTo: lastView.bottomAnchor)
])
}
}
}
class ChildView: NSView {
override var intrinsicContentSize: NSSize {
return CGSize(width: 650, height: 200)
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
NSColor.gray.set()
self.bounds.frame()
}
}