this is something I have a problem with. I have done a bunch of tutorials on constraints in the interface builder and I understand pinning. My app below uses a UITableView and in the UITableView cells there are 4 UIButtons and 4 UILabels. I want to keep the spacing even like below for larger screen sizes. I guess what I mean is I want the spacing to dynamically increase with the screen size but the size of the images remains the same. If I try pinning the left and right UIButtons to their respective edges of the container this distance will not dynamically increase and there will be a big gap in the centre. How can I set it up so the layout is the same that for the smaller screen size?
You can add some transparent views to the superview, and use them as spacers. I thought this was weird at first, but I noticed that Apple recommends it (it even turns up as a suggestion in one of their amazingly informative NSLayout debug messages)
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:
#"H:|[spacer1][view1]\
[spacer2(==spacer1)][view2]\
[spacer3(==spacer1)][view3]\
[spacer4(==spacer1)][view4]\
[spacer5(==spacer1)]|"
options:NSLayoutFormatAlignAllTop
metrics:0
views:viewsDictionary]];
The trick, as you see, is to set each spacer's width as equal to the first spacer. Then you will get even distribution of your visible views. In you case, you would add each of your button/image combos to a container view (view1 ... view4).
In the storyboard...
The blue views represent the (transparent) spacer views. This is the setting to get them to resizeable equal widths. You should also set the visible button/imageview combos to fixed widths.
Although this example says 'add two constraints' it actually adds four, all marked as 'equal width to view' - but it seems to do the right thing. You will also want to set the space between each view ('spacing to nearest neighbour') to zero.
Related
I'm currently setting up a login screen that should ultimately look something like this:
I've successfully accomplished all the constraints needed to create the desired look on all screen sizes, however, I can not seem to figure out the constraint needed to correctly align the "Don't have an account? Signup". I've designed it so the "Don't have an account?" is a UILabel, and "Signup" is a UIButton. I've just aligned these side by side.
The UILabel, "Don't have an account?", has the following constraints:
The UIButton, "Signup, has the following constraints:
These constraints seem to accomplish what they need to on screen sizes 4" and below. however the 4.7 inch, and 5.5 inch (iPads excluded), have wide spacing between the UILabel and UIButton. I've read Ray Wenderlich's tutorial on auto layout, and still can not figure out the problem (I'm new to auto layout, but I have an idea what I'm doing. I'm not just adding random constraints hoping it works).
This is what it looks like on all my targeted devices:
Notice as screen size increases, so does the gap in between the label and button. Any help is appreciated.
You are setting the leading space of the label to its superview, and you are setting the trailing space of the button to its superview. So obviously if the superview gets wider, they are going to get further apart.
So if that's not what you want, don't do that.
The actual solution to what you want to do is quite tricky. You want these two objects to behave as a group, and you want that group to be centered. There's no simple way to express that. You will need to make a group. In other words, you will need a container view, give that view an absolute width and center it, and put these two objects inside the container.
New in iOS 9, a UIStackView can help you with this.
Another approach that works is to use a couple UIViews as spacers. I sometimes prefer this to containment, but it is probably a matter of taste.
Remove the leading constraint from your UILabel.
Remove the trailing constraint from your UIButton.
Add a UIView with clear background in front of your UILabel. Set a leading constraint from this UIView to the container leading edge with constant 0. Set a trailing constraint to the UILabel with constant 0.
Similarly, add another UIView after your UIButton. Set a leading constraint from this UIView to the UIButton with constant 0. Set a trailing constraint from this UIView to the container trailing edge with constant 0.
Both UIViews will need a Y position and height. These are somewhat arbitrary so I would set Align Center-Y constraints with your UILabel, and height constraints of say 5.
Here's where the magic happens: select both UIViews and set an Equal Widths constraint. This forces the UIViews to occupy equal space on both sides.
UIStackView is overkill for this situation. Just
Put the label and button in a single UIView.
Constrain the label's left and center Y to the container view.
Constrain the button's right and center Y to the container view.
Constrain the label's right edge to the button's left edge.
Set the horizontal content hugging priority of the containing view to 1000.
Constrain the containing view's center X to its superview.
You can do it to your existing code only by setting few constraints. And this would work on all resolutions even on the iPad. You don't need to group them , i have attached the images to show the constraints that i have applied.
And for the button set this constraints
It would be shown properly on all the devices kindly have look as to how it looks on all the resolutions and also in the landscape mode of each resolution
Thanks
Omkar
I created a scroll view in Xcode that works awesome because of this video.
https://www.youtube.com/watch?v=3PIm8-lKAYw
When I was messing around after I made it I found out that if I clicked on the scroll view and went to Show the Size Inspector or the fifth button on the right hand side of the screen I had the option to make a constraint called Top Space change in value that caused the scroll view to become bigger and smaller. I decided to see if I could find a way to change the constraint programmatically by simply using dot notation and the equaling it to an int value that I wanted.
So what I'm trying to figure out is there a simple way to change these constraints values programmatically that change the scroll view constraints values?
Without actually following that tutorial (and there being no code in your question) I'm going to make a few assumptions.
Yes, it is possible to change the scroll view's content size by manipulating constraints in your code. If you are creating the constraints in a xib or storyboard, you will need to make sure they are hooked up to IBOutlets so that you can access them in your code.
If you have 2 views arranged vertically that affect the vertical content size of your scroll view, increasing the space between these views would also increase the vertical size of your scrollview's content size. The following would increase the space between 2 views by 20 (assuming a multiplier of 1) and subsequently increase the scrollview's vertical space by the same amount.
// This is a vertical space constraint created in your xib or storyboard between 2 views that drive the content size of your scrollview
someVerticalSpaceConstraint.constant += 20;
I am trying to get into the Auto Layout business, but i find it kinda hard.
I am trying to get 5 image views to display next to each other in the center of the view. They need to resize themselves to expand their height / width as well.
This is how it looks in IB (and kinda the way it needs to look when running the app):
So i have the following constraints:
Added aspect ratio of 1:1 so that they will always be squared
First button is "hugging" the left side of the view, so it will be displayed in the side.
The following 4 buttons have a horizontal spacing to the button next to them
Each button has a constraint to the top and bottom of the screen, so they will get bigger if you resize the screen.
However, when i run it, it looks like this:
And i am just kinda stumped here. What am i doing wrong?
Thanks in advance,
Best Regards - /JBJ
** EDIT **
I added a trailing constraint to the last button. This makes sure they are all within the screen, but is kinda problematic when thinking about the size of it, so that didn't solve it either.
* EDIT EDIT *
Tried removing the top and bottom constraint since they are the ones forcing the size up. Added a vertical center constraint to them all. This won't work either. Displaying them very small (lined up nicely, but too small) and also comes with warnings:
OK, here goes...
Add 5 buttons to the view... No constraints.
Add horizontal space constraints between them all. Also add constraints from the first and last view to the superview. I've also changed the last constraint to 0 (notice the +306 telling me it's currently out of place).
Select all the buttons and (using the add Constraint button) add "Equal Widths" to them all. Notice the orange dotted outline telling me they now all will have equal widths.
Now align them in the vertical centre of the view with this button...
The last thing to do is to go to each one and add the 1:1 aspect ratio. You'll need to add the constraint and then edit it to a 1 ratio.
Make sure you update the frames once you're done to reposition the buttons to their new constraints...
The preview screen shows this working at all different sizes...
For placing them at the centre of the screen vertically use
NSLayoutConstraint *constraintHorizontal = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:attribute
multiplier:1.0f
constant:0.0f];
For placing them horizontally
Button width = (width of the screen)-(button spacing dimension)- (left distance)- (right distance)/5;
Same for height.
Initial left constraint for the first image view will be left distance.
What I always do in such a situation is just simply think.
How much constraints do I need to 100% define the design? What should I write to tell someone on the phone what it looks like?
In your case this are the following constraints (hope I wont forget one)
They are all squares (equal width height, not a value)
They have equal size, just set it to equal, not to a value
Horizontal spacing between elements and edge, set it to fixed size
Vertically centered
Place 5 buttons vertically and horizontally center in UIView
Select all of them and embed them in a stack view
Change distribution to fill equally.
Adjust spacing in attribute inspector to make space between buttons.
Add leading and trailing space and height constraint to stack view. Also vertically align it.
I want to make similar ui for all iPhones & i am currently using auto layout for that, but i do not know how to create this `UI` using `NSLayoutConstraint`?
This UI works fine in small screen but i want same ui for bigger iPhone as well(keep certain amount of space between buttons). how can i add constraint in this to get same ui as iPhone 4s.
i took UIButton & below titles are UILabel.
Some one help me out here.
Screenshots.
Personally I find that trying to make sense of Auto Layout constraints in code (and using NSLayoutConstraint) to be quite confusing and difficult to understand. VFL (Visual Format Language) is powerful but I would recommend if you are just starting out with Auto Layout then working in Storyboard or a XIB file may be easier (depends on your individual preference).
Since this is quite an involved topic I've put together a sample project for you to reference on GitHub. The benefit of this approach is that there is literally no code - all of the configuration is done in the Storyboard (or can also be done in a XIB file). Highlights of the constraints I created are below however please reference the sample project for specific details:
Background View (Purple) - Constraints pin the top, bottom, left and right sides to the edge of the parent view.
Icon Container View (White) - Constraints pin the bottom, left and right sides; a height is also set which accommodates all of the icons.
All image views have a width constraint and aspect ratio constraint (maintains equal width and height) and all labels are constrained to their appropriate image with the appropriate vertical constraint (top).
The outside corner icons are all constrained only to their corner (top-left, top-right, bottom-left, bottom-right). The center corners are constrained to be centered horizontally inside the view.
If you are just getting started with Auto Layout you may find the following presentation I made helpful in learning the basics.
Here are three screenshots from different simulators which show how the layout adjusts automatically depending on the screen size: iPhone 5s, iPhone 6, and iPhone 6 Plus:
Technically, landscape orientation is also supported by these constraints however the result may or may not fit your requirements. (I am unsure what orientations you are planning to support.)
I don't really want to write the code for your whole view as its not the best way for you to learn and plus I don't have the time right now. Instead, I will tell you the approach I usually take:
Create the view
UIView *myView = [UIView new];
Set translatesAutoresizingMaskIntoConstraints property
myView.translatesAutoresizingMaskIntoConstraints = NO;
Add view as subview
[self.view addSubview:myView];
Add the constraints
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:myView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0];
[self.view addConstraint:constraint];
You need to add multiple constraints in order to layout the view exactly as you want in relation to the other views around it. Top, left (leading), right (trailing) and bottom.
I suggest either creating your own category in order to make writing the constraints quicker and easier to understand when reading it back. Here's one for example: PureLayout
You can also use constraints with a visual format but I often find this can be harder to get your head around.
More reading on the whole subject can be done here
It depends on your requirement and their may be different ways to achieve. But if you ask in this particular case with three items as fixed then following may help:
The buttons at the corners can have constraints with borders.
All the labels can have constraints with their respective buttons to be same width and should be aligned horizontally centred with buttons.
The buttons in centre and buttons at the borders should not have any dependencies with each other.
The buttons in centre can have constraints with top and bottom of the container view.
Buttons in centre should have constraints for horizontally centred with the container view.
You might need to add some more constraints, but based on the above suggestions it will work for any screen size.
Context / What I'd Like to Do
I'm building this for iOS 7
I'm using a StoryBoard
I have two UITableViews, that I'd like to keep the same height and
distance apart, to retain visual consistency between 3.5 & 4 inch devices
So on the shift from a 4 inch screen to 3.5 inch screen I'd like for:
The table views to get shorter but remain equal in height
For the top table view to keep the same y pos
For the bottom table view to shift its y pos up to maintain the same distance between the bottom of the top table view and the top of the bottom table view. AKA the same gap between them
What I've Tried
Using the Pin Icon in the storyboard I've selected both TableViews and set their heights to equal and included this code in the view controller:
[self.topTableView addConstraint:[NSLayoutConstraint
constraintWithItem:self.bottomTableView
attribute:NSLayoutAttributeBottom relatedBy:0
toItem:self.bottomTableView attribute:NSLayoutAttributeTop
multiplier:1 constant:30]];
Question
How do I keep them the same height while retaining the same distance
Update
Check out the Apple suggested way to do this (it's in the section titled "Creating Equal Spacing Between Views").
Edit: Apple now favors the use of stack views for this purpose. See this WWDC 2013 video for OS X and this iOS one from WWDC 2015
They don't present a constraints-only solution. Instead, they suggest placing hidden "spacer views" between your visible views.
The reasoning behind this is rooted in the way the constraint system works. Constraint relationships are always strictly between two objects. In a spacing constraint, that relationship must be between the thing that's being spaced, and the thing it's X space from. That's it. There's no room for a third relation to make the space (itself the result of a relation) equal to some other value.
Height (and width) constraints, on the other hand, are not relations. You can set the height of a thing with a simple constant that's unrelated to anything else. Thus there's "room" to specify a relationship to another object — that a height should be equal to another height (or width, or whatever), for example.
So if you ever find yourself wanting constraints that are all related in some way to each other, look to heights and widths instead of spaces. In your particular example, you can surround your UITableViews with hidden UIViews, set their heights to be equal, and their space to neighbors/containers to 0 or some other low constant.
As an added bonus, this is all possible in IB. No need for custom code or subclasses.
The top table view should have a constraint to the top of the superview (or the top layout constraint), a vertical spacing constraint to the bottom table view, and a height constraint. The bottom table view should have a constraint to the bottom of the superview and an equal height constraint with the top table view. The key thing you need, is to make the priority of the top table view's height constraint less than 1000, so that when the height of the screen changes, the one thing that isn't mandatory (that <1000 height constraint) will be the thing that adjusts. All of this can be set up in IB.
After Edit:
Actually, you don't need the height constraint on the top table view at all. Since I have constraints to the top and bottom of the superview, as well as one between the two table views, having a constraint that makes the heights of the table views equal is all you need.