【问题标题】:How to give an NSOutlineView a tiled background image that scrolls?如何给 NSOutlineView 一个滚动的平铺背景图像?
【发布时间】:2020-05-27 09:40:27
【问题描述】:

我有一个标准的NSOutlineView。我希望它有一个背景图像,它垂直平铺,并与大纲视图单元格一起滚动。

我在 ViewController 中使用以下内容在某种程度上实现了这一点:

class ViewController: NSViewController {

    @IBOutlet weak var outlineView: NSOutlineView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        if let image = NSImage(named: "tile") {
            let color = NSColor.init(patternImage: image)
            outlineView.backgroundColor = color
        }
    }
}

这有效,除非您滚动超过视图的顶部或底部(使用包含滚动视图提供的拉伸)。

我尝试将背景图像放在滚动视图上,但它是静态的,不会随着大纲视图的内容滚动。

我还尝试在视图层次结构中对各种对象进行子类化并覆盖它们的 draw(_ dirtyRect: NSRect) 方法并执行以下操作:

self.wantsLayer = true
self.layer?.backgroundColor = ...etc

但也没有成功。

谁能给点建议?

【问题讨论】:

  • 你在draw(...方法中直接将NSImage绘制到视图上吗?
  • 我不记得尝试过,不。它可能奏效了?无论如何,我确实找到了另一种解决方案,如下所示。

标签: swift cocoa nsoutlineview


【解决方案1】:

我最终创建了一个新的自定义NSView

class MyView: NSView {

    override func draw(_ dirtyRect: NSRect) {
        if let image = NSImage(named: "Tile") {
            let color = NSColor.init(patternImage: image)
            color.setFill()
            dirtyRect.fill()
        }

        super.draw(dirtyRect)
    }
}

然后在我的ViewController 类中,我添加了一个自定义视图的实例,并使用自动布局约束将新视图固定到我的outlineView 的剪辑视图,从它上面2000 点开始,到下面2000 点结束。这意味着无论您过度滚动到拉伸区域多远,您仍然可以看到平铺背景。

class MyViewController: NSViewController {
    @IBOutlet weak var outlineView: NSOutlineView!

    override func viewDidLoad() {
        super.viewDidLoad()
        guard let clipView = self.outlineView.superview else { return }

        let newView = MyView(frame: .zero) // Frame is set by autolayout below.
        newView.translatesAutoresizingMaskIntoConstraints = false

        clipView.addSubview(newView, positioned: .below, relativeTo: self.outlineView)

        // Add autolayout constraints to pin the new view to the clipView.
        // See https://apple.co/3c6EMcH
        newView.leadingAnchor.constraint(equalTo: clipView.leadingAnchor).isActive = true
        newView.widthAnchor.constraint(equalTo: clipView.widthAnchor).isActive = true
        newView.topAnchor.constraint(equalTo: clipView.topAnchor, constant: -2000).isActive = true
        newView.bottomAnchor.constraint(equalTo: clipView.bottomAnchor, constant: 2000).isActive = true
    }
}

我已经从上面删除了其他代码,所以希望我留下了说明解决方案所需的一切。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-11
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多