UITableview标题使用VSL的水平和垂直约束

时间:2017-06-24 13:33:05

标签: ios uitableview swift3 visual-format-language

我有一个带标签和按钮的标题视图。我正在添加这样的约束:

//create a view, button and label
view.addSubview(label)
view.addSubview(button)

label.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false

let views = ["label": label, "button": button, "view": view]

let horizontallayoutContraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-19-[label]-60-[button]-22-|", options: .alignAllCenterY, metrics: nil, views: views)
view.addConstraints(horizontallayoutContraints)

let verticalLayoutContraint = NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0)
view.addConstraint(verticalLayoutContraint)

return view

这非常有效,但现在我想添加一个横跨标签和按钮上方宽度的分隔视图。像这样:

let frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 10)
let divView = UIView(frame: frame)
divView.backgroundColor = UIColor.lightGray

我似乎无法弄清楚实现这一点的约束组合。基本上我希望divView跨越tableview的宽度,现有的视图位于它下面。理想情况下,我可以像这样嵌套:

V:|[divView]-20-[H:|-19-[label]-60-[button]-22-|]-20-|

那里的任何专家可以帮助我解决这个问题吗?我可以制作一个NIB,但我更愿意以编程方式进行。

1 个答案:

答案 0 :(得分:1)

当然,我在视觉格式语言方面做得非常非常少,但就我所知,你不能以这种方式嵌套

根据您想要获得的最终结果以及可能添加到此视图的其他内容(标签?图片等),您可能会更容易使用{ {1}}或两个。

但是,这里有一个使用VFL的例子...这将在Playground中按原样运行,因此很容易进行调整以查看效果。另请注意,我采用了两种方式 - 将标签和按钮与分隔线对齐,或者将分隔线与标签和按钮对齐。评论和UIStackView块应该是不言自明的。颜色只是为了让人们很容易看到元素框架的最终位置。

if

编辑:这是另一种变体。

这次,“标题视图”将只有 x,y位置设置...其宽度和高度将由其内容自动确定。

灰色“div”视图的位置和宽度将通过将其约束到标签和按钮来控制,该标签和按钮将使用您指定的值:

import UIKit
import PlaygroundSupport

let container = UIView(frame: CGRect(x: 0, y: 0, width: 600, height: 600))

container.backgroundColor = UIColor.green

PlaygroundPage.current.liveView = container

// at this point, we have a 600 x 600 green square to use as a playground "canvas"

// create a 400x100 view at x: 40 , y: 40 as a "header view"
let headerView = UIView(frame: CGRect(x: 40, y: 40, width: 400, height: 100))
headerView.backgroundColor = UIColor.blue

// add the Header View to our "main container view"
container.addSubview(headerView)


var label: UILabel = {
    let l = UILabel()
    l.backgroundColor = UIColor.yellow
    l.text = "The Label"
    return l
}()

var button: UIButton = {
    let l = UIButton()
    l.backgroundColor = UIColor.red
    l.setTitle("The Button", for: .normal)
    return l
}()

var divView: UIView = {
    let v = UIView()
    v.backgroundColor = UIColor.lightGray
    return v
}()


headerView.addSubview(divView)
headerView.addSubview(label)
headerView.addSubview(button)

divView.translatesAutoresizingMaskIntoConstraints = false
label.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false

var vcs: [NSLayoutConstraint]

var views = ["divView": divView, "label": label, "button": button, "headerView": headerView]


let bAlignToDivider = true

if bAlignToDivider {

    // use the width of the divView to control the left/right edges of the label and button

    // V: pin divView to the top, with a height of 10
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "V:|[divView(10)]", options: [], metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // H: pin divView 20 from the left, and 20 from the right
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "H:|-20-[divView]-20-|", options: [], metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // V: pin label to bottom of divView (plus spacing of 8)
    //    using .alignAllLeft will pin the label's left to the divView's left
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "V:[divView]-8-[label]", options: .alignAllLeft, metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // V: pin button to bottom of divView (plus spacing of 8)
    //    using .alignAllRight will pin the button's right to the divView's right
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "V:[divView]-8-[button]", options: .alignAllRight, metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // H: add ">=0" spacing between label and button, so they use intrinsic widths
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "H:[label]-(>=0)-[button]", options: .alignAllCenterY, metrics: nil, views: views)
    headerView.addConstraints(vcs)

}
else
{

    // use left/right edges of the label and button to control the width of the divView

    // H: pin label 20 from left
    //    pin button 20 from right
    //    use ">=0" spacing between label and button, so they use intrinsic widths
    //    also use .alignAllCenterY to vertically align them
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "H:|-20-[label]-(>=0)-[button]-20-|", options: .alignAllCenterY, metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // V: pin divView to the top, with a height of 10
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "V:|[divView(10)]", options: [], metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // V: pin label to bottom of divView (plus spacing of 8)
    //    using .alignAllLeft will pin the divView's left to the label's left
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "V:[divView]-8-[label]", options: .alignAllLeft, metrics: nil, views: views)
    headerView.addConstraints(vcs)

    // V: pin button to bottom of divView (plus spacing of 8)
    //    using .alignAllRight will pin the divView's right to the button's right
    vcs = NSLayoutConstraint.constraints(withVisualFormat:
        "V:[divView]-8-[button]", options: .alignAllRight, metrics: nil, views: views)
    headerView.addConstraints(vcs)

}

同样,您可以将其复制/粘贴到游乐场页面中......

"H:|-19-[label]-60-[button]-22-|"