Search code examples
iosiphoneswiftuitoolbar

My UIButtonBarItem 's don't properly lay out with FlexibleSpace


I'm programmatically creating a UIToolBar and its Items in swift :

    var items = [UIBarButtonItem]()
    let leftButton  = UIBarButtonItem(image: UIImage(named: "left"), style: .Plain, target: self, action: Selector("doneClickedMaButton"))
    let spacer      = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
    let rightButton = UIBarButtonItem(image: UIImage(named: "right"), style: .Plain, target: self, action: Selector("doneClickedRight"))
    let searchButton = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: Selector("doneClickedSearch"))
    items.append(leftButton)
    items.append(spacer)
    items.append(searchButton)
    items.append(spacer)        
    items.append(rightButton)

var toolBar         = UIToolbar()
    toolBar.frame = CGRectMake(0, 0, self.view.frame.size.width, 50)
    toolBar.translatesAutoresizingMaskIntoConstraints = false
    toolBar.backgroundColor = UIColor.redColor()
    toolBar.items = items
    toolBar.sizeToFit()
    view.addSubview(toolBar)
    view.addConstraint(NSLayoutConstraint(item: toolBar, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0.0))

If I don't add the spacer item, then the simulator looks like this :

enter image description here

If I do have them in, like it says so in this code. I get this :

enter image description here

As you can see here, not only are the images now falling off the screen towards the left, but they're no longer in the right order.

I thought .FlexibleSpace just adds dynamic spacing between items. Am I missing something here? Someone mentioned in various posts that one could set widths to a UILabel within a UIBarButtonItem, and that could make .FlexibleSpace recognize it.


Solution

  • The problem is you do not have enough constraints to satisfy the auto layout engine. You are pinning the tool bar to the bottom but the width is shrinking so that it only accommodates the buttons, but you would like it to be the width of your view. Try something like:

    var items = [UIBarButtonItem]()
        let leftButton  = UIBarButtonItem(image: UIImage(named: "left"), style: .Plain, target: self, action: Selector("doneClickedMaButton"))
        let spacer      = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil)
        let rightButton = UIBarButtonItem(image: UIImage(named: "right"), style: .Plain, target: self, action: Selector("doneClickedRight"))
        let searchButton = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: Selector("doneClickedSearch"))
        items.append(leftButton)
        items.append(spacer)
        items.append(searchButton)
        items.append(spacer)        
        items.append(rightButton)
    
    var toolBar         = UIToolbar()
        toolBar.frame = CGRectMake(0, 0, self.view.frame.size.width, 50)
        toolBar.translatesAutoresizingMaskIntoConstraints = false
        toolBar.backgroundColor = UIColor.redColor()
        toolBar.items = items
        toolBar.sizeToFit()
        view.addSubview(toolBar)
        toolBar.leadingAnchor.constraintEqualToAnchor(self.view.leadingAnchor).active = true
        toolBar.trailingAnchor.constraintEqualToAnchor(self.view.trailingAnchor).active = true
        toolBar.bottomAnchor.constraintEqualToAnchor(self.view.bottomAnchor).active = true