Adding relative constraints the iOS layout - ios

I want to set relative constraints to layout elements like the image below:
1) the white square must be on the top right corner filling 50% of the horizontal content.
2) the central globe must be relative to the screen size. example: on 3.5 inch device must be smaller, on 5.5 must be greater. like 75% of the screen width.

0) Clear all constraints for sanity.
.
.
1/4 SQUARE
1) Resize your view to kind-of fit the intended size.
2) Select the square view and add margin constraints.
3) multiselect the root view and the view
4) Add equality constraint of width and height.
5) Select the equal height constraint and then the equal width constraint and change the multiplier to 2 for both constraints.
DONE

0) Clear all constraints for sanity.
. .
CIRCLE
1) Put the circle view roughly into the middle.
2) Select it and add these two constraints.
3) This circle is a UIView which is a rectangle so it has width and height that are independent from each other....but we need to keep them equal..so we need to put an Aspect Ratio Constraint.
4) And finally ..we need to give it some size (width == height here). Let's make the size dependent on root view width. Multiselect again both the circle view and the root view..and add the equal width constraint. Also experiment with ratio. 1.6 looks good to me for a start.

Related

Set view as percentage of width in portrait and percentage of height in landscape, in interface builder using autolayout

I am creating a launch screen that has a centered image. I want the image to be 0.7 of the width in portrait orientation and 0.7 of the height in landscape orientation, so the image is the same size in both orientations, but relative to device size. It would be smaller on iPhones and larger on iPads, while supporting both orientations on iPad.
I can do one of those constraints but not both. For example, if I make it 0.7 of the width in portrait then it looks good in portrait but then oversized in landscape, and vice versa.
How do I create such autolayout purely in interface builder? (I'm assuming launch screens must only use IB.)
The trick is to add two sets of proportional width and height constraints...
First:
centerX
centerY
1:1 aspect ratio
Then:
width <= 0.7 #1000
width = 0.7 #750
height <= 0.7 #1000
height = 0.7 #750
So our constraints are saying:
try to make width and height each at 70% -- Priority: 750 (High, but not Required)
but keep the image view at 1:1 ratio -- Priority: 1000 (Required)
and neither width nor height can be greater than 70% -- Priority: 1000 (Required)
Here's how it looks in the Document Outline pane:
and here's what we get for iPad 9.7":
and iPhone 11:
You need to make constraints in respective of the view. For that, you need to follow the steps mentioned below :
Select your imageView.
Hold the control key and move your cursor to the main view.
Now click Equal widths constraint and give it the desired multiplier.
Repeat the above steps for the Equal Height constraint.
You are ready to go.
To make this work requires adding the equal widths constraints (per #Saumya Gautam's answer - welcome to SO!) but requires a little more tweaking to give the results.
Create equal width constraints to desired percentage (image to super view).
Update constraints: set one of them to "less than or equal" relation and set the other at a priority less than the first, e.g. 900.
Create aspect ratio (1:1) constraint on image.
Constraints:
Result, in portrait:
In landscape:

Resizing buttons and position on a static background image

I am working to have my buttons height and position adapt to screen size changes like the pictures shown above. The buttons themselves will remain clear and only serve as a simple way to handle taps that trigger the segues to different screens. My goal is to make it so that as the image stretches across different screen sizes, I would like the buttons to keep equal height and width and position with the windows. I know that if the windows had properties I could simply make the buttons have an equal size and width to them and be done, but as I mentioned the image is static and it has to stay that way for the time being. I've tried creating constraints for the buttons and that has only proven to be a headache and I don't know if stack views will help me here either, I know this is fairly complex, but I'm ok with that I just need some direction.
UPDATE: In an effort to follow the instructions LGP listed properly I started from step 1. As I mentioned in the comments, I believe it's simply the ratio and the constraints conflicts since when I remove one or two it works fine, but then how do I set the constraints so it fills the entire screen and maintains the ratio of the picture? Also shown are the constraint conflicts for the image view an it isn't showing the aspect ratio of the parent container view either
If you want to do it in interface builder it is not too hard. You should use spacer views and proportional sizes to position the buttons. That way, whatever size your background will have, all the elements will follow.
1. Create a container that has the same proportions as you image. Add a regular UIView and set an Aspect Ratio constraint with a multiplier of 852:568. This is the dimension of your background photo, 852 x 568 pixels, but the actual values don't matter, as long as the aspect ratio is the same. (Don't forget to also tie up the container view to however you want it in your view controller. See the UPDATE below on how to do this.)
2. Place the background image in the container. Add an image view as a child to the container. Set the constraints to touch all four edges of the container. Set the Image property to you image, and set Content Mode to Aspect Fit.
3. Add the first spacer view. Add a regular UIView to the container view (see leftmost, white view below) and set the constraints as follows:
height = 1 (not important, I used 10 in the image)
Top space to Superview = 90 (not important)
Leading space to Superview = 0
Width equal to Superview with multiplier dw:cw <- This makes it proportional! dw is the distance from the left edge to the first window/button, and cw is the width of the container. If your container is 375 wide, and your distance to the first button is 105, the multiplier will be 105:375.
4. Add the second space view. This is the vertical spacer, going from top to first button. Set it up similar as the first spacer, except make the height proportional to the containers height, and the width fixed.
5. Add the first button. Constrain its left and top edges to the spacers, then make its width and height proportional to the container.
6. Add the remaining spacers and buttons. They are all the same. Just remember where to make them proportional. All buttons are constraint to the single vertical spacer.
Finally, you should make the spacer views hidden. You can easily try it within your Storyboard by selecting different devices.
I chose to add everything on iPhone 8, but it is not really important. Here is what it looks like when I change to iPad Pro 12.9" and iPhone SE. Note how the buttons are positioned correctly. The spacer move around a little because they have partly fixed distances, but it works fine anyway.
UPDATE: Here is how to constrain the container view in the view controller's view to make the container fill the whole view and still keep its aspect ratio.
First, set the image view's (the one you added in step 2 above) Content Compression Resistance Priority to 200 for both Horizontal and Vertical. This will allow the image to compress rather then expand if it has a choice.
Second, Add the following constraints to you container:
Align Center X to Superview
Align Center Y to Superview
Equal Width to Superview >= 0
Equal Height to Superview >= 0
852:568 Ratio to View <- This you should already have!
Now the container will always center on screen, it will always fill at least the entire screen, but will also allow it to fill beyond in both X and Y.
UPDATE 2: If you want to ignore the photo's aspect ratio, and always fill the screen with the photo, you just add constraints for the container view to each side to its superview. Your container view's constraints should look like this.
In step 2 you will need to set the image's Content Mode to Scale to fill. The rest should be the same.
Use percentage based positions and size. Identify the positions of windows in percentage basis, and create the origin in x and y dimension by multiplying the percentage to the width and height of the screen. I am assuming that you are using ScaleToFill as content mode of the ImageView.
Similarly for calculating size, identify the width and height of the ImageView on percentage basis, and multiply the values in percent with the total width and height of the screen.
For example, to calculate the position of Window one-
Suppose, window1.x in percentage basis is 25% & total image view width is 400 (for example), than window1.x pixel position will be-
window1X = (25 * 400) / 100 = 100
Suppose, window1.y in percentage basis is 25% & total image view height is 300 (for example), than window1.y pixel position will be-
window1Y = (25 * 300) / 100 = 75
Suppose, width is 7% of image views width, than width in pixel will be -
window1Width = (7 * 400) /100 = 28
Suppose, height is 12% of image views height, than height in pixel will be -
window1Height = (12 * 300) /100 = 36
window1.frame = CGRectMake (window1X, window1Y, window1Width, window1Height)
Same approach for other windows, to calculate their positions(size will be same as window 1)
This approach will work across all screen resolutions, since it uses percentage based calculations & ScaleToFill as content mode for image view.

View changes size depending on device screen size, but should have a fixed size

I have created an orange circle using a UIView100 height and 100 width with a radius of 50. This was done in the 4 inch setup.
When i move up to the 4.7inch or higher the circle becomes distorted.
What do i do so that the circle doesn't get distorted when displayed on larger devices?
So I guess you used Xcode's “Reset to Suggested Constraints” option, like this:
When you do that, Xcode guesses what constraints you want. Unfortunately, in your case, it guessed wrong. It did create the centering constraints you wanted, but it did not create the width and height constraints you wanted. Instead it created leading edge and top edge constraints, like this:
So when you load your scene on a larger device, in order to satisfy those constraints, auto layout has to make the view larger, like this:
To fix this, you need to delete the edge constraints:
And add width and height constraints:
So your final constraints on the subview look like this:
With these constraints, when you load your scene on a larger device, the subview will stay centered and not change size:
I'm betting you used a fixed corner radius to make a circular UIView (which would have a constraint for 1:1 aspect ratio too). Just make it so the radius of the corners is calculated somewhere where the right dimensions for the view can be known. viewDidLayoutSubviews is a good place as it'll take care of other resizes like screen rotation.
override func viewDidLayoutSubviews() {
self.circleView.layer.cornerRadius = self.circleView.frame.size.width / 2 // Assumes width == height because of 1:1 aspect ratio constraint
}
Alternatively don't make the size of your view depend on the width or height of the screen (i.e. remove constraints to the sides, center it and give it a fixed width and height)

How to use Autolayout to achieve result as per shown screen

I'm developing an app where I'm facing an issue to achieve one UI layout only for iPhone devices. This is the layout that I'd like to achieve:
I want to achieve overlapped views that layout should be same on every device from 5s to 7 plus.
The key is setting proportional constraints.
Start with adding a UIView to hold the 4 elements - background, man, woman and heart.
Add a UIImage for the background, and pin the edges to the edges of the view - that's the easy part.
Add a UIImage for the Man...
Set the Aspect Ratio to 1:1 to keep it square (well, round in this case).
Set the Height constraint equal to the Height of the "containing" view, but then set the multiplier to less than 1 to make it relative to the view. In this case, 0.6 is pretty close.
Set constraints for Centered Horizontally and Vertically... then set the Multipliers to keep the image left and above the centers. 0.64 on horizontal, and 0.9 on vertical work pretty good.
Add a UIImage for the Woman...
Set the Height and Width constraints equal to the Man image.
Set constraints for Centered Horizontally and Vertically... then set the Multipliers to keep the image right and below the centers. 1.4 on horizontal, and 1.2 on vertical work pretty good.
Add a UIImage for the Heart...
Set the Aspect Ratio to 1:1 (or whatever gives you the proper ratio for your heart image).
Set the Height constraint equal to the Height of the "containing" view, but then set the multiplier to less than 1 to make it relative to the view. In this case, 0.15 is pretty close.
Set constraints for Centered Horizontally and Vertically... then it will need a little adjustment o note Vertical 1.05 worked for me.
Now, you just need to set appropriate constraints for the "containing" view, and all the elements will scale and position themselves within it.
When you're all done, it should (hopefully) look like this:
I put the project up in a GitHub repo for you to look at: https://github.com/DonMag/AnotherLayoutExample

How to change the height of the view based on width

My views width will change according to the device width but I want to change the height according to that I don't want that to be static.
I couldn't find any constraint that can take care of this.
I heard aspect ratio can do this. But I tried It doesn't seem to work.
How it is generally achieved?
Use concept of aspect ratio with AutoLayout to update your view with respect to height & width. Use multiplier to update aspect ratio. Here are snap of aspect ration assignment and how to update it's multiplier
Logic of Multiplier:
1:1 = Height and width of your image will remain same
2:1 = Your width or height is 2x with respect to each other and create a rectangle. Here Height will be 2x or width will be 2x, it depends upon first item and second item in constraint.
Logic of Priority:
Priority assigns, priority to specific constraint when it conflicts with another constraint of same view. e.g. if you have set a view with 1:1 aspect ratio, with 100 height & 100 width and centred in Main View. Now you also assign Left (margin)/Leading constraint as fix value like 200. In that case for different size of screen width, Centred alignment and/or Leading alignment and/or aspect ration will conflict each other. At this point you need to update priority between 0-1000, according to your requirement for adjustment of design.
Share me your design, I will give your exact logic, how to use this concept
Try with following easy way..
1) Give Leading and Trailing Constraint like below image.
2) Now set Top or Bottom or Other Constraint as per your design. For me i have settled Vertically Center.
3) Now set Height of UIView as per your Ratio which you want in design and after selecting that view just Drag and Drop on same view and select Aspect Ratio. XCode will automatically get Ratio Constraint. For ref. see below image.

Resources