Question

I'm trying to make a keyboard. I have 9 buttons inside a view with: width and height <= 75. On iPhone 5 works perfectly. But the iPhone 4 buttons are stretched and the size is still 75. Could anyone help me?

Was it helpful?

Solution

The problem is that your telling the views (buttons) to have a height or width >= 75 which means you have an ambiguous layout (someone already mentioned this) - you can check for this by examining the hasAmbiguousLayout property of your view. It's likely not working on the iPhone 5 correctly either it just so happens that when you've run it autolayout has found the solution you're looking for so it appears to work. Run it enough times and eventually you'll probably get the undesired layout. Ah the joys of autolayout. Anyways one solution to this problem is to set the height and width of one button, and then tell all the other buttons to follow suite. The visual format language guide has an example of this but i'll show you what I mean.

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button1(75)[button2(==button1)[button3(==button1)]|"
                                                                     options:0
                                                                     metrics:nil
                                                                       views:NSDictionaryOfVariableBindings(button1, button2, button3)]];

Then do something similar to lay them out vertically. When autolayout runs it should find the correct layout for them. The next problem comes in how you use it. If you did all this work in a subclass of UIView and then went ahead and made that views width something crazy like 400 pt wide then autolayout will break - in this case because we pinned to the left and right sides. To fix this problem I'd probably remove the the last | and not pin the right side of button3 to the right side of the superview.

The other option you have is to specify constrains using the long format. For Example

//set button1 width to 75
[self.view addConstraint:[NSLayoutConstraint
                          constraintWithItem:button1
                          attribute:NSLayoutAttributeWidth
                          relatedBy:NSLayoutRelationEqual
                          toItem:nil
                          attribute:NSLayoutAttributeNotAnAttribute
                          multiplier:1
                          constant:75]];

//set button2 width == button1
[self.view addConstraint:[NSLayoutConstraint
                          constraintWithItem:button2
                          attribute:NSLayoutAttributeWidth
                          relatedBy:NSLayoutRelationEqual
                          toItem:button1
                          attribute:NSLayoutAttributeWidth
                          multiplier:1
                          constant:0]];

//pin button1 to the left
[self.view addConstraint:[NSLayoutConstraint
                          constraintWithItem:button1
                          attribute:NSLayoutAttributeLeft
                          relatedBy:NSLayoutRelationEqual
                          toItem:self.view
                          attribute:NSLayoutAttributeLeft
                          multiplier:1
                          constant:0]];

//pin button2 to button1
[self.view addConstraint:[NSLayoutConstraint
                          constraintWithItem:button2
                          attribute:NSLayoutAttributeLeft
                          relatedBy:NSLayoutRelationEqual
                          toItem:button1
                          attribute:NSLayoutAttributeRight
                          multiplier:1
                          constant:0]];

OTHER TIPS

Have you considered changing the height programmatically? Here is a stub of code I use.

     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    //iPad Code 
}else{
    if([[UIScreen mainScreen] bounds].size.height > 560){
         //iPhone 5 Code 
    }else{
        // iPhone 4 Code
    }
}

First of all your basic design should be iPhone 4.
It will be much easier to increase the screen design than to shrink it.

Now, regarding your question, it depends on what you want to achieve.
(1) Do you want only the top and the bottom padding to change in different devices?
(2) Do you want the buttons to have different sizes in different devices?
(3) Do you want the spaces between the buttons to be different in different devices?

Anyway, you should set a constraints for equal width and equal height for all the buttons.

From now on, the easiest solution (1) is to put all the buttons in one container that will have a constant height and will be centered in the screen.
This way there will be lower or higher padding around the buttons on different devices.

If you want the spaces between the buttons to change (2) then you can create a matrix of views (imagine sudoku), make all the views have equal widths and heights (constraints) and zero space between them (also constraints), put a button in the center of each view (constraints).
This way the buttons will remain in the same size but the spaces between them will grow or shrink.

Let me know if you understand the above solutions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top