Margin and padding for UI elements in iOS - ios

I have so far developed for Android. There, you can set layoutMargin and padding for almost every UI element (when you describe UI in xml file).
How is this done in code for UIViews in iOS (if there is a common command)?
Tnx

iOS employs a different approach to control placement - there's no layouting engine, you specify absolute coordinates and size for all controls. Kinda like the AbsoluteLayout in Android.
So the concepts of margin and padding don't really apply - the gaps between adjacent controls are completely up to you, they're not computed by the system. Same for sizes.
This makes it more difficult to implement the scenario of "make this control as large as it needs to be for its text". However, you won't run into rogue line wraps.
EDIT: AbsoluteLayout is deprecated these days.

You lay out your UI elements either in code or using Interface Builder (or the .xib editor in Xcode 4). You'll specify actual coordinates for your views, but you can also specify the resizing behavior for each view. So, you can say that a particular view should always keep the same size and remain horizontally centered, or that it should keep it's size and maintain the margin on the left, or that it should stretch to keep both left and right margins, etc. Look for the "autosizing" section in IB, or set the autoresizingMask property of any view in code.

In ios you can use Interface Builder for design. You can still use xml, but no one use this.

Related

Xcode Interface Builder - Make compound map multiscreen compatible

Got a map which is composed of multiple parts:
Each part is an UIButton with an Image. I positioned everything to make up the map and it first looks all right. The problem I have is about resizing the View for different screens sizes. Tried with Autoresizing and Constraints but couldn't get it to look properly for minimizing and maximizing it. The parts should always sick together and up-/downscale according to the screen size. I'm testing the behaviour directly in the Interface Builder by resizing xib's dimensions.
What works is setting all arrows in autoresizingMask for each UIButton and maximizing the view. But minimizing it distorts the map.
Unfortunately it's the first time for me working with the Interface Builder in Xcode. Here you find the source files. Thanks!
Edit:
Setting only the arrows for width and height in the autoresizingMask makes it possible to downscale without distortion. Upscaling pulls the parts apart. How to support proper up-/downscaling simultaneously?
Edit1:
Replaced the every UIButton with UIImage which resize properly in the Interface Builder! See repo here. Unfortunately on simualtor devices the Autoresizing differs and the map-parts don't stick together anymore. Setting the size of UIView in Main.storyboard exactly to xib's size the Autoresizing works perfectly (tested on multiple devices). But later on in the "real" project I'm not in control over the parent's view dimensions.
Played a litte bit with this line of code and it seems to be responsible for "blocking" Autoresizing. How to avoid that? Thanks in advance. I think I’m maybe mixing up Autoresizing with AspectFit which seems to have no effect.
I guess it would be much easier if all the Bundesländer images had the same size. Put them all on top of each other in a common view. Give all the buttons zero padding to all side. Subclass UIButton to check if the the touch event is on a non transparent pixel. Search for "irregular button ios" to find out more about it.
I am able to achieve this using this images, which have all the same size, border added to demonstrate size
and this constraints
The most important constraint might be the Aspect Ratio Constraint on MapWrapper, the view that contains all the buttons.
Using Ole Begemann's OBShapedButton
Some notes:
Your image content is perfect for factorised graphics. Export them to pdf and add them as such as single scale to your assets
you should not include the states names' in the images, but use it as the buttons titles'. To position them correctly, use title insets.
example project: https://github.com/vikingosegundo/germanStateSelection

UITableViewCell margin inconsistency (Static cells)

I have an interesting issue with a margin inconsistency between different devices. Here are 2 screenshots from iPhone X and iPhone 6+ respectively with the same iOS (11.4.1) and running the same app.
You can see that on the iPhone X everything is aligned properly (as well as in IB), but on the iPhone 6+ there's a 4 pixel inconsistency.
This is a table view with static cells. All the menu items are the Basic style, except the second one ("Offline mode") which is in Custom style with custom constraints. In basic style the UILabels have X=16. My custom constraint also has a constant value of 16.
Of course, I can change my custom constraint to 20, but then the situation flips. So on the iPhone 6+ it will be all aligned properly, but will be misaligned on the iPhone X.
I tried to find out where these 4 pixels are coming from, but found nothing. Please help.
The problem is that you have pinned your label's leading edge to the edge of the content view with a constant of 16. That is not how the other cells work, so you get different results.
Instead, pin your label's leading edge to the left margin of the content view, with a constant of 0. The left margin is 16 on a smaller device and 20 on a larger device, which is exactly the difference you're seeing for the other cells (because that is exactly how they are configured).
Matt's answer is correct. I just want to add more details, because it may be beneficial for someone else. So, it turns out that all I need to do is to check the following checkbox in my constraint properties in IB:
Looks pretty simple when you know where to look for.
Generally as soon as you start needing to control the margins etc of table view cells your best bet is to leave the built-in stuff behind and make custom UITableViewCell subclasses with explicit constraints and subviews.
In this particular case the screen width is different and the basic cell type calculates its margin constraints relative to the screen width. If you look on the right side you will see the same kind of inconsistency with the positioning of your switch control relative to the disclosure indicator in other cells.
(EDIT: Easiest solution, depending on what you're aiming for, is as matt suggests, pin to the margin of the content view rather and the actual edge.)
If you want, you could adjust your own constraint on your custom cell so that it is not constant but relative. You could figure out what multiplier you would need by looking at a few different device screen sizes to see if it's constant (e.g. iPhone 6, SE etc). But it may be more practical in the long run to use your own subclasses. Note you generally do want to use relative constraints for things like this, since your constant margins might look fine on one screen size but weird on another.
This is not ideal but technically you could also check what device the user is using (or what the view's width is) and return an appropriate constraint using a switch. Although, if you really are only concerned about the iPhone X vs the 6+, then you might want to consider doing that.
You might also want to consider using a form library like Eureka but there's a bit of a learning curve with anything like that, especially when it comes to customizing the appearance of cells and their subviews.

Why are constraints preferred over autoresizing in Xcode?

In Xcode, when using the autoresizing option for any type of object, things seem to stay where they're supposed to be while maintaining a proportional size to the scene. I generally just select the inside arrows in the autoresizing box and everything maintains adequate sizes and proportions. However, I've seen multiple times on tutorials, blogs and videos that using constraints is "the right way". Why would the use of constraints be better than autoresizing when autoresizing seems to work perfectly? Would any problem surge when using autoresizing if I work only on iPhone in portrait mode?
Well there are a two reasons I think. The first is probably the most accurate, but might leave you feeling weird after. Because Apple is pushing it. Usually when apple is backing a new tool in their api, its wise to follow because they will drop support for old things you get used to like Autoresizing. Kinda sucks I know.
The second (better) reason that Autolayout will let you write view components that you can reuse between many different screen sizes. Yea Autoresizing helps, but Autolayout gives you more control when the screen size makes a large change like from iPhone to iPad. I've written views that live in all my iphone/ipad/apple tv apps.
An important reason is to allow views showing text, such as labels or buttons with titles, to adapt to the text content and font.
The text content should change due to internationalization/localization.
The font can change if Apple changes the system font or if the user asks for larger text to make reading easier.
With proper application of auto layout, your layout can adapt to such changes and still look good. Without auto layout, you would need to manually alter the layout to accommodate such changes.

iOS Simulator not displaying correctly in Xcode 6

I've been having such a hard time trying to figure out how this thing works. It's so random and I have no idea what else to try. I've looked up multiple articles on this issue and everyone just says change the scale. Changed the scale does not help, it's got nothing to do with what's happening here. I'm not sure if this is related to the bottom of Xcode where you can change the dimensions (Any vs Any / Any vs Regular Height, etc...) I've asked my mobile development teacher at school as well and he couldn't figure it out either. Any help would be greatly appreciated!!
Picture below:
http://tinypic.com/r/281fw5w/8
Your problem is not scaling. What you need to look at is auto layout and constraints.
You can use the icons in the lower right edge of the interface builder to get at them or control drag from a view controller (like a button, label, etc.) to the containing view (or any other view controller for that matter.) Usually, the main view window itself. When you release you can now add constraints to "attach" the element to that other element relatively. For instance, you could attach the things on the left to the left side and the things on the right to the right side. Now, regardless of the dimension of the actual device screen, those elements will appear in those locations relative to the device screen.
The problem is that the position of elements from your perspective is right for the canvas you see in the Interface builder, but once the app is run, the real canvas has different dimensions.
To manage the position, size and other attributes of UI elements, there is a system called AutoLayout.
It is quite ingenious because it is similar to natural language.
For example "I want this element to be in the middle of the screen."
or
"I want this element to be 20 pixels from the left corner and 57 pixels from the element that is above this element."
By combining these rules you basically create a set of layout constraints, that are applied in runtime to the view hierarchy and view are laid out properly.
Autolayout allows for very sophisticated layouts.
Another aspect you need to take into account that you might want your app to look well in all form factors from 3.5 inch iPhone up to iPad air.
Since these devices differ considerably in size, Apple introduced an abstraction called Size Class.
Size Class is an abstraction on top of concrete size. Concrete iOS devices have vey concrete dimensions. But in natural language you often say it's big ,or small ,or normal. And this the level of abstraction size classes use.
For each size class you can have a particular set of auto layout constraints.
So by combining AutoLayout and SizeClasses, Apple solved the problem oh how to have one application but one that can still accommodate specific form factors and can adjust its layout to them.
In Xcode6, all storyboards/xib files have autolayout & sizeclasses enabled by default. Interface builder provides you with a comfortable environment where you can set up your layout by creating constraints for each size class combination.

in an iOS app, how can I get 2 elements to sit next to each other?

I'm new to iOS development and I'm working through my first tutorial. One thing the tutorial kind of skipped over is positioning. I have a list where each cell has an image with some text next to it. At least in Interface Builder that's how it appears. When I actually run the app the image appears on top of the text (i.e. both have the same exact positioning from the left-hand side of the screen).
Interface Builder:
Running App:
I essentially want what, in CSS lingo, would be "float: left", or even just relative positioning with x/y coordinates for each element (i.e. if it would look the same/similar when running the app as it appears in the storyboard), that would be great.
In playing with all of various View attributes, I'm not finding anything that will position the views… I can find attributes that will position them in Interface Builder, but none of those settings seem to carry over to the app when it is running, and the image/text always appear on top of each other.
I apologize for the newbie question… it's probably something simple/obvious that has somehow slipped by me.
If you are using Xcode5 to do the test, the app will use AutoLayout feature by default. And the constraint you made for this layout seems to be wrong.If you want to position the views to the right place with AutoLayout ,you need to read some material from apple official website.If you do not have too much time to learn,you can try to edit xib without AutoLayout. You can disable AutoLayout in "file inspector" of interface builder.
If you are new to iOS development (as I am), you should familiarize yourself with AutoLayout, as suggested in Eric's answer.
If you're looking for a quick fix to the question as asked, all of the following options worked for me:
Select the label, then select the Horizontal Space Constraint and delete it.
Select the label and hit cmd-plus (i.e. cmd+shift+equals). This will delete all of the positioning constraints at once.
Turn off AutoLayout.
There are other ways to fix the problem I was having, but generally the issue was incorrect AutoLayout constraints.
If you feel comfortable in the code, I suggest manually setting the frame to a CGRect that you define with CGRectMake(origin.x, origin.y, width, height). You can also do this with the autolayout settings but I find that programmatically positioning elements gives me much more flexibility, and, as a programmer, it's much easier than trying to figure out the options in interface builder.
The iOS coordinate system is top-down, meaning that y=0 is the top of the screen and y=568 is the bottom of the screen (on iPhone 5). X is 0 on the left side of the screen.
Coordinate systems are relative to the view that they are in. In your case, your elements are in a UITableCell, which is given its own coordinate system by the rendering engine. So if you want your image to be 10px from the top and 10px from the left of the cell's edge (a la padding:10px in css), you would set its frame like so:
image.frame = CGRectMake(10, 10, 50, 50)
...assuming the image is 50x50.

Resources