Search code examples
iosswiftrotationautolayoutuitoolbar

UIToolbar doesn't fit the screen


I made a a custom keyboard toolBar:

enter image description here

To do that I created a toolbar

let keyboardToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 44))

and a view for the banner

adToolbar = GADBannerView(frame: CGRectMake(0, 44, self.view.bounds.size.width, 44))

then I grouped them in another UIToolbar (I tried UIView too)

let clusterView = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 88))
clusterView.addSubview(adToolbar)
clusterView.addSubview(keyboardToolbar)

and I added the view to the UITextField's keyboard.

Everything ok, but when I rotate the device happens this:

clusterView UIToolbar resize correctly but not the two contained bars... (clusterView UIToolbar resize correctly but not the two contained bars...)

I tried with

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    methodWhichGeneratesToolbar() 
}

But it's the same, what can I try to solve this issue?

P.S.: I've made an example project.


Solution

  • Here's a suggestion on how to do it with programmatic autolayout using Visual Format Language (VFL). You'll need to have a look at the VFL docs to understand the VFL string syntax (They are pinning the outer view to the top and sides of the main view, and pinning the two subviews inside and to each other, and setting their height to 44).

    I don't have AdMob installed, so I used a regular UIView instead of the banner view, but hopefully it should resize similarly - this code works ok on the 9.2 simulator in a test app

    let keyboardToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 44))
    keyboardToolbar.translatesAutoresizingMaskIntoConstraints = false //This is critical for all programmatic autolayout - if you forget it nothing will work
    
    
    let adToolbar = UIView(frame: CGRectMake(0, 44, self.view.bounds.size.width, 44))
    adToolbar.translatesAutoresizingMaskIntoConstraints = false
    
    
    let clusterView = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 88))
    clusterView.translatesAutoresizingMaskIntoConstraints = false
    
    //Map views to keys used in visual format language strings
    let views = ["keyboardToolbar":keyboardToolbar,"adToolbar":adToolbar,"clusterView":clusterView]
    
    //Map values to strings used in vfl strings
    let metrics = ["barHeight":44]
    
    //In named variables to make it clear what they are
    //Syntax is explained in link above
    let verticalConstraintsStr = "V:|[keyboardToolbar(barHeight)][adToolbar(barHeight)]|"
    let adHorizontalConstraintsStr = "|[adToolbar]|"
    let keyboardHorizontalConstraintsStr = "|[keyboardToolbar]|"
    
    let subViewConstraintStrs = [
      verticalConstraintsStr,
      adHorizontalConstraintsStr,
      keyboardHorizontalConstraintsStr
    ]
    
    
    //Views must be added to subviews before adding constraints
    // if the superview is referenced using
    //the | symbol in the VFL strings
    
    clusterView.addSubview(keyboardToolbar)
    clusterView.addSubview(adToolbar)
    
    //Converts strings to constraints for subviews and add them
    
    for constraintStr in subViewConstraintStrs {
      let allConstraints = NSLayoutConstraint.constraintsWithVisualFormat(constraintStr, options: NSLayoutFormatOptions(rawValue: 0), metrics: metrics, views: views) 
      clusterView.addConstraints(allConstraints)
    
    }
    
    let clusterVerticalConstraintsStr = "V:|[clusterView]" //Note no | at the end - no bottom pin
    let clusterHorizontalConstraintsStr = "|[clusterView]|"
    
    view.addSubview(clusterView)
    
    //Same process for the enclosing view
    
    for constraintStr in [clusterVerticalConstraintsStr,clusterHorizontalConstraintsStr] {
            let allConstraints = NSLayoutConstraint.constraintsWithVisualFormat(constraintStr, options: NSLayoutFormatOptions(rawValue: 0), metrics: metrics, views: views)
            view.addConstraints(allConstraints)
        }
    

    VFL is powerful but annoying to debug, and can't do all types of constraint (e.g. not alignments - you have to use an even more verbose API for those).