使视图居中并填充可用高度而不离开屏幕

Have view centered and fill available height without going offscreen

我遇到这样一种情况,我希望视图在其父视图中居中,保持正方形,但在不偏离边缘的情况下尽可能多地填充高度,即,它应该查看可用的垂直和水平 space,选择 2.

中最小的

还有 2 个视图,一个在下方,一个在上方,它们要么是按钮,要么是标签。这些视图的 bottom/top 应该附加到中央视图的 top/bottom 上。我可以在一定程度上让它发挥作用,但我将在下面解释我的问题,以及到目前为止我得到的结果:

顶部标签有:

中心视图有:

底部按钮有:

运行 这看起来不错,并产生了预期的结果:

但是,如果我将视图作为自定义 class 的实例并添加 UIButton 子视图,一切都会出错。在这个 class 我执行:

self.topLeftButton = CustomButtonClass()
self.topLeftButton.setTranslatesAutoresizingMaskIntoConstraints(false)
self.addSubview(self.topLeftButton)

self.addConstraints([
        NSLayoutConstraint(item: self.topLeftButton, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 0),
        NSLayoutConstraint(item: self.topLeftButton, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1, constant: 0),
        NSLayoutConstraint(item: self.topLeftButton, attribute: .Height, relatedBy: .Equal, toItem: self, attribute: .Height, multiplier: 0.5, constant: 0),
        NSLayoutConstraint(item: self.topLeftButton, attribute: .Width, relatedBy: .Equal, toItem: self.topLeftButton, attribute: .Width, multiplier: 1, constant: 0)
        ])

使用此代码,视图将折叠为以下内容:

我不明白这是为什么。我在这里和那里做了一些小的调整,但没有设法让它按预期工作。如果我在 IB 中添加相同的按钮,视图将再次折叠,并且按钮的高度似乎不会增加。

在现实生活中,我不会将 UIButton 子类化,但在我的回答中已经做了,因为这就是问题所指示的。 UIButton 通过组合达到最佳效果。所以也许最好创建一个 UIButton,然后修改它的属性。

class FooViewController: UIViewController {

    override func viewDidLoad() {

        var view = CustomView()
        view.backgroundColor = UIColor.darkGrayColor()

        var label = UILabel()
        label.text = "Label"

        var button = UIButton.buttonWithType(.System) as UIButton
        button.setTitle("Button", forState: .Normal)

        view.setTranslatesAutoresizingMaskIntoConstraints(false)
        label.setTranslatesAutoresizingMaskIntoConstraints(false)
        button.setTranslatesAutoresizingMaskIntoConstraints(false)

        self.view.addSubview(view)
        self.view.addSubview(label)
        self.view.addSubview(button)

        // The width should be as big as possible...
        var maxWidthConstraint = NSLayoutConstraint(item: view, attribute: .Width, relatedBy: .Equal, toItem: view.superview, attribute: .Width, multiplier: 1, constant: 0);
        // ... but not at the expense of other constraints
        maxWidthConstraint.priority = 1

        self.view.addConstraints([
                // Max width, if possible
                maxWidthConstraint,
                // Width and height can't be bigger than the container
                NSLayoutConstraint(item: view, attribute: .Width, relatedBy: .LessThanOrEqual, toItem: view.superview, attribute: .Width, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: view, attribute: .Width, relatedBy: .LessThanOrEqual, toItem: view.superview, attribute: .Height, multiplier: 1, constant: 0),
                // Width and height are equal
                NSLayoutConstraint(item: view, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1, constant: 0),
                // View is centered
                NSLayoutConstraint(item: view, attribute: .CenterX, relatedBy: .Equal, toItem: view.superview, attribute: .CenterX, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: view, attribute: .CenterY, relatedBy: .Equal, toItem: view.superview, attribute: .CenterY, multiplier: 1, constant: 0),
        ])

        // Label above view
        self.view.addConstraints([
                NSLayoutConstraint(item: label, attribute: .Top, relatedBy: .GreaterThanOrEqual, toItem: label.superview, attribute: .Top, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: label, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: label, attribute: .Right, relatedBy: .LessThanOrEqual, toItem: view, attribute: .Right, multiplier: 1, constant: 0),
        ])

        // Button below view
        self.view.addConstraints([
                NSLayoutConstraint(item: button, attribute: .Bottom, relatedBy: .LessThanOrEqual, toItem: button.superview, attribute: .Bottom, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: button, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: button, attribute: .Right, relatedBy: .LessThanOrEqual, toItem: view, attribute: .Right, multiplier: 1, constant: 0),
        ])

    }
}


class CustomView: UIView {

    required init(coder: NSCoder) {
        super.init(coder: coder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    override init() {

        super.init()
        var button = CustomButton()
        button.setTitle("Custom Button", forState: UIControlState.Normal)
        button.setTranslatesAutoresizingMaskIntoConstraints(false)

        self.addSubview(button)

        // Custom button in the top left
        self.addConstraints([
                NSLayoutConstraint(item: button, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: button, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1, constant: 0),

        ])
    }
}


class CustomButton: UIButton {

    required init(coder: NSCoder) {
        super.init(coder: coder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    override init() {
        super.init()
        self.backgroundColor = UIColor.greenColor()
    }
}