NSView无法正确裁剪NSStackView子视图

时间:2018-12-29 21:45:02

标签: swift cocoa autolayout nslayoutconstraint

我有一个 NSStackView ,其中装有 NSTextView 项。我正在尝试在父级NSView小于NSStackView时剪切stackview ,但是我没有运气。

这是我看到的两个问题场景:
1)完全不剪裁
我设置了NSView的框架:

let v = NSView(frame: NSMakeRect(0, 0, 1024.0, 768.0))
v.addSubview(rawStack)

即使父视图的大小似乎正确(我可以看到红色的bg颜色),stackView的大小也是完整的,并且没有被裁剪。

2)发生剪切,但是显示了错误的stackView子项
当我限制stackView 2的高度时,会发生奇怪的事情: rawStack.heightAnchor.constraint(lessThanOrEqualToConstant: 768).isActive = true

a)当stackView太小时,它会增加一些stackView子级以填充剩余空间(不需要)。我可以通过仅在stackView太大时应用约束来解决此问题。

b)当stackView太大时,它将height=0设置为错误的stackView子视图。我希望它可以显示孩子0,1,2,3,4或适合的孩子数。而是显示2,3,5,6,7。另外,我收到大量Will attempt to recover by breaking constraint <NSLayoutConstraint:0x60000008bcc0 '# Tip top height' NSTextView:0x600000122f80.height >= 156.713 (active)>

这样的约束警告

我尝试设置NSStackView.setVisibilityPriority(),该设置几乎奏效。问题是,如果不合适,它会隐藏整个子视图。如果需要,我希望将其部分裁剪。

有什么想法吗?

当前代码:

func swapView(newView:NSView) {
    let viewToShowNext = generateDetailSlide(newView: newView)
    scrollView.documentView = viewToShowNext
}


func generateDetailSlide(newView:NSView) -> FlippedView {

    let rawStack = newView as! FlippedStackView
    rawStack.identifier = NSUserInterfaceItemIdentifier(rawValue: "RAWSTACK###")



    if (rawStack.frame.size.height > 768) {
      // rawStack.heightAnchor.constraint(lessThanOrEqualToConstant: 768).isActive = true
    }

    rawStack.widthAnchor.constraint(lessThanOrEqualToConstant: 1024).isActive = true


    for (i,view) in rawStack.arrangedSubviews.enumerated() {
        Swift.print("### Frame", view.frame)
        Swift.print("### Bounds", view.bounds)
        //view.widthAnchor.constraint(equalToConstant: 700.0)
        let length = rawStack.arrangedSubviews.count
        let priority = Float(length - i) // highest priority for lowest items
        // hide any beyond 4

        view.setContentCompressionResistancePriority(.init(rawValue: priority * 1000), for: .vertical)
        view.exerciseAmbiguityInLayout() // try this?!?

        // rawStack.setVisibilityPriority(.init(rawValue: priority), for: view)


    }

    rawStack.setContentCompressionResistancePriority(.defaultLow, for: .vertical)


    Swift.print("clippingResistance", rawStack.clippingResistancePriority(for: .vertical))


    rawStack.layoutSubtreeIfNeeded() 

    let v = NSView(frame: NSMakeRect(0, 0, 1024.0, 768.0))
    v.addSubview(rawStack)


    return v
}


func makeTextField(content: String, type:String, globalConfig: GlobalConfig) ->  NSTextView {
    var style = getStringFromDict(cssObj: globalConfig.defaultStyles)

    var html = "<span style=\"\(style)\">\(content)</span>"
    let titleData = Data(html.utf8)

    let NSAttrStr = try? NSMutableAttributedString(data: titleData, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)

    let textStorage:NSTextStorage = NSTextStorage(attributedString: NSAttrStr!)
    let manager:NSLayoutManager = NSLayoutManager()

    let container:NSTextContainer = NSTextContainer(containerSize: NSMakeSize(800, 400))
    // tie it all together so text shows up
    textStorage.addLayoutManager(manager)
    manager.addTextContainer(container)

    // appears to have no effect? These sizes don't seem to matter...
    let windowFrame:NSRect = NSRect(x: 0, y: 0, width: 800, height: 200)
    let textView:NSTextView = NSTextView(frame: windowFrame, textContainer: container)

    textView.backgroundColor = globalConfig.bgColor

    textView.isEditable = false
    textView.alignment = .left

    // get size of textView content. This works!
    textView.layoutManager?.ensureLayout(for: container)
    let sz = textView.layoutManager?.usedRect(for: container).size

    let c1 = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: (sz?.height)!)
    c1.isActive = true
    c1.identifier = "\(content) height"
    // does this one even make a difference?
    let c2 = textView.widthAnchor.constraint(greaterThanOrEqualToConstant: ((sz?.width)! + 20))
    c2.isActive = true
    c2.identifier = "\(content) width"


    return textView
}

0 个答案:

没有答案