Нежелательная высота кнопки рассчитывается с использованием языка визуального форматирования

У меня есть UIViewController с четырьмя UIButtons (2 x 2) на нем, который я выложил в конструкторе интерфейсов, который работал отлично. У меня будет бесплатная версия приложения с поддержкой рекламы, поэтому мне нужно переделать эту сцену для загрузки в зависимости от того, является ли приложение платным или с поддержкой рекламы. Исходя из этого, я пытаюсь использовать язык визуального форматирования, чтобы выложить представление. Я получаю неправильные значения для моего UIButton высоты, несмотря на учет их, когда я их вычисляю. Я не могу понять свою ошибку (или упущение?).

Вот скриншот моего конструктора интерфейса.

У меня нет ограничений на мои кнопки в конструкторе интерфейсов, но у меня есть IBOutlets подключен к MyViewController, MyViewController находится в контроллере навигации и имеет панель вкладок внизу.

Я создал метод под названием layoutButtons что я звоню в viewDidLoad сразу после super.viewDidLoad(), Вот:

func layoutButtons() {
    // Configure layout constraints

    // Remove interface builder constraints from storyboard
    view.removeConstraints(view.constraints)

    // create array to dump constraints into
    var allConstraints = [NSLayoutConstraint]()

    // determine screen size
    let screenSize: CGRect = UIScreen.mainScreen().bounds

    let navBarRect = navigationController!.navigationBar.frame
    let navBarHeight = navBarRect.height

    let tabBarRect = tabBarController!.tabBar.frame
    let tabBarHeight: CGFloat = tabBarRect.height

    // calculate button width based on screen size

    // padding for left + middle + right = 8.0 + 8.0 + 8.0 = 24.0
    let buttonWidth = (screenSize.width - 24.0) / 2

    /*
    My buttons are extending under the top & bottom layout guides despite accounting
    for them when I set the buttonHeight.
    */

    // padding for top + middle + bottom = 8.0 + 8.0 + 8.0 = 24.0
    let buttonHeight = (screenSize.height - topLayoutGuide.length - bottomLayoutGuide.length - 24.0) / 2

    // create dictionary of metrics
    let metrics = ["buttonWidth": buttonWidth,
        "buttonHeight": buttonHeight,
        "navBarHeight": navBarHeight,
        "tabBarHeight": tabBarHeight,
        "bannerAdWidth": bannerAdWidth,
        "bannerAdHeight": bannerAdHeight]

    // create dictionary of views
    var views: [String : AnyObject] = ["firstButton": firstButton,
        "secondButton": secondButton,
        "thirdButton": thirdButton,
        "fourthButton": fourthButton,
        "topLayoutGuide": topLayoutGuide,
        "bottomLayoutGuide": bottomLayoutGuide]

    let topRowHorizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "H:|-[firstButton(buttonWidth)]-[secondButton(buttonWidth)]-|",
        options: [.AlignAllCenterY],
        metrics: metrics,
        views: views)
    allConstraints += topRowHorizontalConstraints

    let bottomRowHorizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "H:|-[thirdButton(buttonWidth)]-[fourthButton(buttonWidth)]-|",
        options: [.AlignAllCenterY],
        metrics: metrics,
        views: views)
    allConstraints += bottomRowHorizontalConstraints

    let leftColumnVerticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "V:|[topLayoutGuide]-[firstButton(buttonHeight)]-[thirdButton(buttonHeight)]-[bottomLayoutGuide]|",
        options: [],
        metrics: metrics,
        views: views)
    allConstraints += leftColumnVerticalConstraints

    let rightColumnVerticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "V:|[topLayoutGuide]-[secondButton(buttonHeight)]-[fourthButton(buttonHeight)]-[bottomLayoutGuide]|",
        options: [],
        metrics: metrics,
        views: views)
    allConstraints += rightColumnVerticalConstraints

    NSLayoutConstraint.activateConstraints(allConstraints)
}

Я возился с моим buttonHeight переменная, но каждая итерация, которую я пробовал, приводит к появлению кнопок, расширяющихся под topLayoutGuide а также bottomLayoutGuide, Вот как это выглядит во время выполнения:

Я приветствую любые предложения, где искать свою ошибку. Спасибо за чтение.

1 ответ

Решение

Первоначально я следовал учебнику по языку визуального формата Рэя Вендерлиха, и настройка учебника была похожа на мою в том, что subViews были на раскадровке и подключены к MyViewController с IBOutlets,

В отчаянии я снял раскадровку и создал UIButtons в коде. Попутно я обнаружил, что моя проблема заключалась в том, что я устанавливал изображение на кнопке до ее размещения. Мораль этой истории не в том, чтобы устанавливать образы на UIButtons пока они не выложены!

Ниже приведен код, вызываемый из метода в моем viewDidLoad это расположение 2х2 сетки кнопок:

    // Configure Buttons
    firstButton.translatesAutoresizingMaskIntoConstraints = false
    // code to customize button

    secondButton.translatesAutoresizingMaskIntoConstraints = false
    // code to customize button

    thirdButton.translatesAutoresizingMaskIntoConstraints = false
    // code to customize button

    fourthButton.translatesAutoresizingMaskIntoConstraints = false
    // code to customize button

    // Add buttons to the subview
    view.addSubview(firstButton)
    view.addSubview(secondButton)
    view.addSubview(thirdButton)
    view.addSubview(fourthButton)

    // create views dictionary
    var allConstraints = [NSLayoutConstraint]()

    let views: [String : AnyObject] = ["firstButton": firstButton,
        "secondButton": secondButton,
        "thirdButton": thirdButton,
        "fourthButton": fourthButton,
        "topLayoutGuide": topLayoutGuide,
        "bottomLayoutGuide": bottomLayoutGuide]

    // Calculate width and height of buttons
    // 24.0 = left padding + middle padding + right padding
    let buttonWidth = (screenSize.width - 24.0) / 2
    let buttonHeight = (screenSize.height - topLayoutGuide.length - bottomLayoutGuide.length - 24.0) / 2

    // Create a dictionary of metrics
    let metrics = ["buttonWidth": buttonWidth,
    "buttonHeight" : buttonHeight]

    let topVerticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "V:|[topLayoutGuide]-[firstButton(buttonHeight)]",
        options: [],
        metrics: metrics,
        views: views)
    allConstraints += topVerticalConstraints

    let topRowHorizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "H:|-[firstButton(buttonWidth)]-[secondButton(==firstButton)]-|",
        options: NSLayoutFormatOptions.AlignAllCenterY,
        metrics: metrics,
        views: views)
    allConstraints += topRowHorizontalConstraints

    let bottomRowHorizontalContraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "H:|-[thirdButton(buttonWidth)]-[fourthButton(==thirdButton)]-|",
        options: NSLayoutFormatOptions.AlignAllCenterY,
        metrics: metrics,
        views: views)
    allConstraints += bottomRowHorizontalContraints

    let leftColumnVerticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat(
        "V:[firstButton]-[thirdButton(==firstButton)]-[bottomLayoutGuide]-|",
        options: [],
        metrics: metrics,
        views: views)
    allConstraints += leftColumnVerticalConstraints

    let rightColumnVerticalConstriants = NSLayoutConstraint.constraintsWithVisualFormat(
        "V:[secondButton(buttonHeight)]-[fourthButton(==secondButton)]-[bottomLayoutGuide]-|",
        options: [],
        metrics: metrics,
        views: views)
    allConstraints += rightColumnVerticalConstriants

    NSLayoutConstraint.activateConstraints(allConstraints)

    // ** DON'T SET IMAGES ON THE BUTTONS UNTIL THE BUTTONS ARE LAID OUT!!!**
    firstButton.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
    firstButton.setImage(UIImage(named: "first.png"), forState: .Normal)

    secondButton.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
    secondButton.setImage(UIImage(named: "second.png"), forState: .Normal)

    thirdButton.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
    thirdButton.setImage(UIImage(named: "third.png"), forState: .Normal)

    fourthButton.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
    fourthButton.setImage(UIImage(named: "fourth.png"), forState: .Normal)
Другие вопросы по тегам