1

I have created a custom UIView which is loaded from an XIB file. I am then adding the view to a stackview, and setting a width constraint on the item.

It's working perfectly if I do this from the storyboard, however if I'm doing it from Swift, I can't get the view to stretch to the constraint. The stackview is allocating space for the view, but the view doesn't stretch to the space.

Custom view swift code:

import Foundation
import UIKit

@IBDesignable class TabButton: UIView {

@IBOutlet weak var label: UILabel!

@IBInspectable var TabText: String? {
    get {
        return label.text
    }
    set(TabText) {
        label.text = TabText
        label.sizeToFit()
    }
}

override func intrinsicContentSize() -> CGSize {
    return CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric)
}

override init(frame: CGRect) {
    // 1. setup any properties here

    // 2. call super.init(frame:)
    super.init(frame: frame)

    // 3. Setup view from .xib file
    xibSetup()
}

required init(coder aDecoder: NSCoder) {
    // 1. setup any properties here

    // 2. call super.init(coder:)
    super.init(coder: aDecoder)!

    // 3. Setup view from .xib file
    xibSetup()
}

// Our custom view from the XIB file
var view: UIView!

func xibSetup() {
    view = loadViewFromNib()

    // use bounds not frame or it'll be offset
    view.frame = bounds

    // Make the view stretch with containing view
    view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

    // Adding custom subview on top of our view (over any custom drawing > see note below)
    addSubview(view)
}

func loadViewFromNib() -> UIView {

    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: "TabButton", bundle: bundle)
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

    self.roundCorners([.TopLeft, .TopRight], radius: 10)

    return view
}
}

And this is the viewcontroller that is adding the view (tabButton) to the stackview (tabBar):

@IBOutlet weak var tabBar: UIStackView!

override func viewDidLoad() {
    super.viewDidLoad()

    let tabButton = TabButton(frame: CGRectZero)
    tabButton.label.text = "All Videos"

    tabButton.backgroundColor = UIColor.blackColor()

    let widthConstraint = NSLayoutConstraint(item: tabButton, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100)
    tabButton.addConstraint(widthConstraint)

    tabBar.insertArrangedSubview(tabButton, atIndex: 0)
}

I want the tabButton to "ignore" it's frame and resize according to the height of the stackview and the width constraint I'm setting.

What am I missing?

UPDATE:

My constraints on the custom view (basically just a view with a label - But I plan to use this with more complex layouts as well):

My constraints

dthomasen
  • 826
  • 15
  • 32

3 Answers3

1

Try this:

let widthConstraint = NSLayoutConstraint (item: your_item_here, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: your_value_here)
self.view.addConstraint(widthConstraint)
Orkhan Alizade
  • 7,379
  • 14
  • 40
  • 79
  • Nothing happens when adding that. I'm doing it after I've added the item to the stackview. If I do it before I get a runtime error. "'NSInternalInconsistencyException', reason: 'Impossible to set up layout with view hierarchy unprepared for constraint.'" – dthomasen Oct 15 '15 at 09:20
  • Can you paste here an image of your view result? – Orkhan Alizade Oct 15 '15 at 09:23
  • http://postimg.org/image/nty10iqk5/ The neon green bar is the other view in the stackview. The stackview has an equal amount of space in each site, so we can see the constraint is working as it should, it just doesn't resize the content of the custom view. – dthomasen Oct 15 '15 at 09:31
0

At least you should define the sizing of your custom view with sizeThatFits: . Unfortunately, I can't see your layout constraints to tell if it's all right with them.

Community
  • 1
  • 1
Arthur Gevorkyan
  • 2,069
  • 1
  • 18
  • 31
  • Thanks, I've added a screenshot of my constraints for the custom view to the question. How can I define the sizing of the custom view in SizeThatFits? I'm guessing that's based on the constraints set by the superview? – dthomasen Oct 15 '15 at 08:53
  • Looks ordinary. What about sizeThatFits? Have you tried that? – Arthur Gevorkyan Oct 15 '15 at 09:01
  • Yes, doesn't change anything. If I set the frame size for the tabButton using CGRectMake instead of using CGRectZero I can resize the view properly. But I want to do it with the width constraint. – dthomasen Oct 15 '15 at 09:06
0

The stack view manages the layout of its subviews and automatically applies layout constrants for you.So try to add tabButton without any constraint to StackView.

OK,Then check out this thread

Hope this will solve your issue.

Community
  • 1
  • 1
Razz
  • 87
  • 3
  • 21
  • But I want the custom view to have a specific size, and the other view in the stackview to fill the rest. That's why I have to set the width of the custom view. – dthomasen Oct 15 '15 at 08:48