将视图居中并填充可用高度,而无需离开屏幕

时间:2015-01-22 22:29:38

标签: ios autolayout

我有一种情况,我希望视图在其超视图中居中,保持正方形,但尽可能多地填充高度而不会偏离边缘,即它应该查看可用的垂直和水平空间,选择2之间的最小值。

还有2个其他视图,一个在下面,一个在上面,它们都是按钮或标签。这些视图的底部/顶部应附加到中央视图的顶部/底部。我可以在某种程度上让这个工作,但我会在下面解释我的问题,以及我到目前为止所做的事情:

顶级品牌有:

  • .Top> = TopLayoutGuide.Bottom
  • .Top = TopLayoutGuide.Bottom(优先级250
  • .Right = CentralView.Right

中央观点有:

  • 中心X和Y = Superview Center X和Y
  • .Height< = Superview.Width * 0.9
  • .Width = self.Height
  • .Top = TopLabel.Bottom

底部按钮有:

  • .Right = CentralView.Right
  • .Top = CentralView.Bottom
  • .Bottom< =(BottomLayoutGuide.Top - 16)

运行它似乎很好,并产生所需的结果:

Correct Layout

但是,如果我将视图作为我的自定义类的实例并添加UIButton子视图,那么一切都会出错。在本课程中,我执行:

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)
        ])

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

Incorrect Layout

我无法弄清楚为什么会这样。我已经在这里和那里做了一些小的调整,但没有设法让它按照需要工作。如果我在IB中添加相同的按钮,视图又想要再次折叠,就像按钮不会在高度上增长一样。

1 个答案:

答案 0 :(得分:1)

在现实生活中,我不会将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()
    }
}