iOS - UIAutoresizingMask margin : why do I need to set both sides? - ios

My question may appear strange, but with an example it's easier to understand :
I have, let's say an UIButton, that I create and then :
// [...] Create button, add it to view
myButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
If I don't specify UIViewAutoresizingFlexibleRightMargin, my component will not be at the right x-ratio on the screen. Why ? I specified left margin, so my element should be at the good position when I rotate the device... Don't understand the need of the right margin.

When you use both flexible margins, a change in width will be split between the two margins. This is commonly used to keep a view centered.
When you use just one flexible margin, a change in width will all be applied to the one flexible margin. This means the other margin stays the same, no matter how the width changes.

Related

iOS - Swift 4 - Constraints for text fields side by side

I Have a view like so:
And I am trying to add constraints so the text fields are side by side so the auto looks the same no matter the device width, how would I do that?
I have tried the following for all 6 of them:
But it ends up looking like this:
What am I doing wrong?
Ctrl drag from the description TextField to vendor TextField and select Equal Widths from popup
You can also use a vertical stackView where each row is a horizontal 1 with distribution set to Equal spacing and drag the text fields to it that will be more easier
Well, let's look at what we know about the horizontal axis (I assume you've got the vertical axis taken care of). There are two text fields; call them Left and Right. We know these things:
Where Left's leading edge must be
Where Right's trailing edge must be
The distance between Left's trailing and edge and Right's leading edge
The relationship between Left's width and Right's width, i.e. they are equal
Ta-daa:
(A UIStackView would construct these same constraints for you, but in a simple situation like this it's probably more trouble than it's worth.)
There are many ways to do it
I give you two but recommend the first one in your case.
First :
Define a constraint by draging one of your UITextFiled to the other one and set it to “Equal Widths”
You may also be able to define a percentage for each (60-40%) if you like.
Second :
Define a constraint like above (draging) And define a relative ratio (0.5) for UITextField width against its superview. Do it for the other one. You need to go to Object Inspector Tab and change the values if needed (so this requires two constraints, one for each UITextField as each of them are relative to the their superview) this is also a little bit slower than the first approach since margins should be defined with priority.

Constraints to resize buttons to fit any screen - Xcode swift

I don't really understand constraints and have tried many different suggestions found online. All they seem to do is bunch everything up on top of one another or do nothing at all.
I have the following IPad application but I want it to work on any size device, mainly a IPod touch.
The page is simply two buttons that I want to remain the same no matter what screen they're on.
Any help on this appreciated.
It helps to think about points of reference that won't change with different screen sizes. Sometimes you want things on, say the top left corner so you just do constraints to the top and the left.
I'll give you two suggestions
Suggestion One
For your case, it seems like you might want to do constraints off centerY since you want them to be in the middle despite the screen size.
So I would make a constraint to "Center Vertically in Container" and then tap on the constraint and adjust it's value to negative or positive, so that way it's always X pixels above or below the centerY.
Now that's not going to be enough. it knows it's Y position but it doesn't know its height, width, or X position. So you need to add enough constraints to satisfy those.
A few examples:
X/Width: Two constraints to leading and trailing on each button OR Center horizontally and fixed width constraint. (again be careful with fixed width constraints since screen sizes can change, sometimes it's what you want though)
Height: Yeah just give it a height constraint in this case.
Note that this means no matter the screen size they'll always have the same gap between them (and maybe different gaps to the other edges).
Suggestion Two
Use a container view, either a stack view (fill, equal spacing, vertical alignment, a spacing value for gap between) or normal view.
You can make the view a fixed height based off the height and spacing between the buttons you want. Then simply center that container view horizontally and vertically on the super view.
Nonsuggestion
There are certainly other ways (like using buffer views with equal heights constraints. So you'd have an invisible view on top, a view in between and a view on bottom. and you'd give those equal heights constraints and align the buttons to the edges of the invisible views surrounding them. As long as you gave the buttons a fixed height this would work for vertical constraints) but I think these two would probably be the best.

Autolayout problems in bigger devices

I am developing an iPhone app in which, i have made this page using autolayout
but it shows unwanted spaces above Register Me(yellow button) in bigger iPhones
Constraints given are:
top,bottom, leading and trailing with respect to its subviews to all the controls. (there is no warning or misplaced constraints i see in xcode)
Here is the screenshot of iPhone 4s
Here is the screenshot of iPhone 6+
I want to minimize the empty spacing in bigger iPhones...
How do i solve this problem?
Please help and thanks in advance
Heres a suggestion for you. You have roughly seven regions of interest there. First one is the title 'Register Kano .. ' etc. Then there are 5 text entry areas - name, email, password, etc. Finally you have 3 small lines of info text - I would count this as one final area, so 7 in all.
What I would do is create 7 parent UIViews to put that stuff in. I would give them 'equal height' constraints, and make them sit above and below each other with no gap. Then as the iphone screen changes height, those areas stretch out height-wise to fill the area. Heres a rough mockup :
Select all those UIViews and select the 'equal heights' constraint :
Then every view except the bottom one needs these constraints (top, leading trailing to superview 0px)
Then your bottom view needs those plus 'bottom' too :
So all that remains to do is to put your content in each of those boxes, but centre them in terms of vertical position relative to their superview.
If your intent to target iOS 9 users, you should use UIStackView, the provide a lot of flexibility in terms of alignment and distribution.
If not, then you or your design team has to find a solution.
You can update the margin contraints of your controls on big devices.
This would add space between each rows on big screens, will looks better as you ask.
Something like :
myControl.heightConstraint.constant += 20.0f
This is how I would do, but you have to decide how you update your layout for big devices
#Krunal you can use the size class and set the constraints accordingly so it will give a brief idea how to fit the UI design for every device!!
you can set constraints relative to height of your base view. This will make your interface objects evenly distributed over layout. Lets assume you have 8 regions. for registerLabel
registerLabel.leading = baseView.leading
registerLabel.trailing = baseView.trailing
registerLabel.top = baseView.top
registerLabel.bottom = baseView.bottom * (1/8)// it will be always proportional to height of view
then for icons at the beginning firstIcon
firstIcon.leading = baseView.leading + 10
firstIcon.height = firstIcon.width
firstIcon.height = baseView.height*(1/9)// to give a gap between icons
firstIcon.bottom = baseView.bottom * (2/8)
and then you can set textfield's constraints according to firstIcon
for other icons you can go on with 3/8, 4/8, 5/8, 6/8 and set the relative textfields constraints according to that icon.
and lastly for registerMe button
registerButton.leading = baseView.leading
registerButton.trailing = baseView.trailing
registerButton.bottom = baseView.bottom
registerLabel.height = baseView.height * (1/8)
With this approach your icons size also decrease and increase relatively with height of view and all the page will be filled.
baseView is view of controller.
What is happening here, you kept the width according to superview ie phone width, but your height is fixed.
Do one thing instead of giving Height constraint, use aspect ration in combination with leading , trailing and top constraint. When view will stretch widthwise , your component's height will also Increase and fill the extra space for iphone 6.
This is the best thing you can do keeping the same layout and design pattern.
Seems you have given some fixed height in views.
As every element is depends on it above and below elements constraints, this might be possible of empty space.
So try to divide the View part then the dependency of constraints will reduce.
If you don't want to show empty space, then use center horizontally to one of the element which will look good, here it may be the third field.
Then start giving same constraints to Register button. Sure it will help you in resolving this issue.
Hey its the best solution for you is stackView
Combine your objects in single stackView.
You can combine your object vertically and also horizontally.
It will decrease your space and view will arranged in awesome manner.
You can select your objects like this.
Click here to make it stack.
Now you can reduce your space like this.

Same width for a set of labels using auto layout

I need to create a simple layout with a few labels and buttons. Here's how I have positioned the UI elements in the IB.
This is how I want them to look like in the app as well. The label set on the left side with the same width so the elements on the right side will adjust their widths accordingly.
I have set the leading space to superview constraints on the labels on the left side and set vertical spacing between each of them. Similarly I've added trailing space to superview constraint to the labels and buttons on the right side with vertical spacing between each other. I've also added horizontal spacing between each couple of elements (ex: Name <-> John Doe, Telephone <-> button).
When I run it, it looks like this.
The elements only take up widths as their content needs. I assume this problem occurs because there is no way to auto layout to decide on a width. If I set the labels on the left to same width constraint, it doesn't work at runtime because the constants for them are fixed so they looks like this.
How can I make them appear properly like I have them in the interface builder?
Thank you.
I uploaded a test Xcode project with this issue here.
In your final example, it looks like you almost achieved what you wanted. You made all the labels on the left have the same width. You can now set a width constraint on the first label to a width that works for you, and the other labels should automatically match. The only issue you might still have is getting it to look good on wider screens.

Getting two adjacent UILabels to both align on the inside edge

I have a UIView which contains two UILabel objects, which are populated programmatically. I want the left UILabel to be right-aligned, and the right UILabel to be left-aligned. This is my pretty ASCII representation:
___________________
| ______ ______ |
| | ASDF| |ASDF | |
| |______| |______| |
|___________________|
I have tried all sorts of masks and alignment properties to no avail. Here is what I thought the correct solution would be, so perhaps someone can point out the flaw in my understanding.
The container UIView needs UIViewAutoResizingFlexibleWidth so that it can expand to fit labels with variable widths. Both the left and the right UILabel need UIViewAutoResizingFlexibleWidth so that they expand to fit content with variable width. The left UILabel needs UIViewAutoresizingFlexibleRightMargin so that the left margin remains fixed. The right UILabel needs UIViewAutoresizingFlexibleLeftMargin so that the right margin remains fixed.
Conceptual problem with this implementation:
As the texts expand, they could just expand over each other as that would still fit the container
I am having the overlap problem, as well as the right margin does not seem to be fixed like it is supposed to, rather there is just a large gap on the right side.
Does anyone know what might be a solution?
the UILabel view does not automatically resize itself based on text. you might need to call sizeToFit every time you change the text. You also need to handle assigning the number of lines manually if want the text to wrap.
Plus, shouldn't the left label be UIViewAutoresizingFlexibleLeftMargin and vice versa? the other way around.
Two observations:
AutoresizingMasks don't expand a view based upon changes of the view's subviews, but rather on the basis of the change in the superview. That's not of interest here. It's generally more useful on things like when the superview changes dimensions as a result of orientation changes. There are other situations that you might theoretically use autoresizingMasks, but I don't think this is one of them.
More logically, you could simply calculate with width of the text labels necessary to fit the desired text, and then set the UILabel's frame accordingly.
To calculate the size of the two text labels, once you set their text property, could do something like:
CGSize leftSize = [leftLabel.text sizeWithFont:leftLabel.font forWidth:self.view.frame.size.width lineBreakMode:UILineBreakModeWordWrap];
CGSize rightSize = [rightLabel.text sizeWithFont:rightLabel.font forWidth:self.view.frame.size.width lineBreakMode:UILineBreakModeWordWrap];
Now that you know the size of the two labels, you can tweak the frame of the two labels, as well as their superview, accordingly.

Resources