XCode 8 - Change constraints according to orientation - objective-c

Here is my problem.
I have a square image which does not fit on an iPad or iPhone app, as the screens are not square, so i decided to add a UIImageView which:
When the Phone is on Portrait position i add a constraint to the top (-20) and bottom (0) to fill the whole screen aligning X in the center and keeping the aspect ratio to keep the image square even if the screen is bigger or smaller, this means that in both sides i will "loose" part of my image, but that is fine.
When I rotate my phone to landscape position, the screen is widder,so i see a square image in the middle of the screen but a white rectangle in both sides.
I think the sollution to this is when it is on landscape position i need to remove the top and bottom constraints and add one to lead (-20) and one to trail (-20), center the image on Y axis and keep the 1:1 ratio...
But my question is: how to add a constraint to valid for one orientarion and change it to the other?
What is the best approach?
thanks
FP

You don't need to do it programmatically. I recommend you make the view fill the superview -- have one constraint each to top, bottom, left, and right. Then for the UIImageView attributes inspector in Interface Builder, set "View Mode" to Aspect Fill.

I think you have it the wrong way around.
While on portrait you should set trail and lead constraints as your height is bigger than the width, so if you set (0) for trail and lead and 1:1 ratio you are safe that it will fit beautifully. Also center it vertically in container.
On landscape, as the width is bigger than the height, you should set top and bottom (0) and ratio 1:1 and center it horizontally in container.

Related

How to autolayout in Xcode buttons filled with different sized images?

I am working on a project with multiple buttons on a viewcontroller and I used autolayout. I want all the buttons to have equal widths and heights and I have horizontal/vertical spacing like this:
The result on multiple devices is like this:
For the example I gave the buttons a background color, but in fact they will be filled with images of all kinds of sizes. I have image assets (#1x/#2x/#3x) for the buttons. For example, the #2x image assets will never be bigger then 100width and 75height (points).
Some of the button images can be changed by the user. So I want the button size to be ‘independent’ of the images inside. The buttons should NOT resize based on the image ‘inside’.
So I want to first(auto)layout the buttons, without the images ‘filling’ the buttons, so that the buttons will have the optimum size for the biggest sized images in my project (for the #2x image assets as mentioned:100width&75height points).
When I autolayout the buttons, and afterwards fill them with the images, xcode ‘wants’ to let me update the frames because of misplaced views. I do NOT want the images affecting the autolayout.
If I just run the app on the simulator or on a real iphone, it runs fine. But I have all these misplaced views warnings. What should I do? How will I 'tell' Xcode(7.1) that the images should NOT affect the width and heights of the buttons?
I have the feeling I have a slightly wrong approach to this (auto)layout problem, but I can not yet put my finger on it. I think I make some kind of logical error.
Is it good practice to first (auto)layout the buttons and then ‘fill’ with the images? Or should I fill the buttons with the images and then (auto)layout?
Here an example with images which are of equal widths and heights:
Regarding the earlier question about conflicting constraint:
So I want these buttons to have equal width and heights: ideally 100width and 75height in points. The width will be alright, but the heights is somewhat difficult when I am using autolayout for different sized viewcontrollers (with a scrollview on it). I want to use additional constraints that 'says'; the buttons should NOT have a height value lower then 75 points. If I use a fixed height constraint, with 'equal or higher then' 75 points I get a conflict with the equal heights constraints (off course). I guess I should work with priorities, but I tried, and I did NOT succeed yet with it.
How should I proceed?
Help is much appreciated!
Question 1:
Of course you're getting a conflict when setting two height constraints of which one computes to 1/3 of the screen width (≈ 107px excluding padding on the iPhone 4) and the other enforces a minimum height that is bigger than this value (e.g. 120px).
Fortunately there's a way out of this using priorities:
Set the fixed height constraint's priority to a value below the priority of your 'greater or equal' constraint. This way autolayout will choose the fixed height constraint only if its constant is greater or equal to the constant of your 'greater or equal' constraint. Otherwise the constant of your 'greater or equal' constraint will be used as the view's height. Makes sense, right? :)
Question 2:
You can achieve the desired behavior as described in your second question by enforcing a fixed height and width for your image view and setting its content mode to "Aspect Fit". In Interface Builder there's a drop down menu for that:
In your case the best way to give the image view fixed dimensions is to pin all four sides to its superview (because the superview has a well-defined size):
So when you apply these leading, trailing, top and bottom constraints to all your image views the images will automatically resized according to the constraints and the result will look like this:

How to size images for storyboard using auto layout?

I'm using Sketch to create images that will be used in my Xcode 6 auto-layout storyboards. However I can not get the image sizes correct. They always appear too large and overflow the storyboard view controller. Is there a way in Xcode to see the dimensions the storyboard expects? Is there a systematic way to do this...rather than trial and error?
Storyboard, especially in auto layout mode, doesn't expect any dimensions – dimensions will depend on device screen (in reality) or on simulated metrics (in Interface Builder in Xcode).
What matters is aspect ratio and presence of three resource files (three sizes – regular, 2x and 3x).
You can see the list of dimensions here:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
So, let's say you want to insert an image that occupies the whole width of the screen, and the height is chosen automatically so that to keep the aspect ratio. What you could do:
Create images in Sketch with widths of 320, 750 and 1242 pixels. Save them as image.png, image#2x.png, image#3x.png.
Insert image in Interface Builder (Storyboard), add width constraint – equal as superview, instead of height constraint – keep aspect ratio.
If the image looked too big, Interface Builder will complain that preview image doesn't match constraints, you will see a little yellow arrow. Click on it, choose the warning and click again – Xcode will offer you to "Update frame". That will resize the image correctly if necessary. Don't forget to choose correct scaling mode (Aspect fit?) for your image.
Moreover, you can see current width and height of the simulated screen in Metrics tab. But those will change every time you change your preview (simulated) device type.

UIToolbar not resizing when rotating with autolayout, with UIBarButtonItems misplaced

it's the first time I'm seriously using autolayout so I'm sure I'm missing something obvious.
I have a very simple view embedded in a UINavigationController. There are three subviews: a UIWebView, a UIToolbar (which in turn contains three UIBarButtons) and a UIActivityIndicatorView. It's just a basic browser view, basically.
I managed to have everything appear as it should even on rotation, except for the toolbar: if the view is first loaded in vertical orientation, going landscape will not resize the toolbar from 44 to 32 points. Originally, before I wiped everything out, it did resize the toolbar BUT the built-in UIBarButtonItems appeared lower and cut off, as if the toolbar was still 44 points tall but pushed 16 points out of the screen.
If the view is first loaded horizonttaly, the bar is 32 points high but the built-in UIBarButtonItems appear still like that, and rotating to vertical will keep it at 32 points.
I honestly have no idea how to make this work as expected (ie. resize properly when rotated, with the buttons showing properly!), so if anyone could point me in the right direction -- pun intended -- I would be really grateful.
The activity indicator is right in the middle of the frame, with these constraints:
Align Center X to Superview
Align Center Y to Superview
The web view is set to use all available space from the top of the view (including the navbar) up to the top of the toolbar, and has these contraints:
Top Space to Superview
Bottom Space to Toolbar
Align Trailing to Toolbar
Bottom Space to Toolbar (it's actually listed twice)
Align Leading to Toolbar
The toolbar is a mess. It has:
Bottom space to Superview
Align Center X to Superview
Top Space to Web View
Align Trailing to Web View
Top Space to Web View (listed twice)
Leading Space to Superview
Align Leading to Web View
Bottom Space to Bottom Layout Guide
The problem is that by not adding any constraints at all, the web view is much bigger than it should be, and the toolbar doesn't even show.
I mostly set these constraints using the horizontal and vertical red bars (similar to springs and strouts) in the 'pin' popover for autolayout, but I'm starting to think that's not the most appropriate approach.
Note that I'm not trying to use autolayout within the toolbar, I read that it wouldn't work and I'm just using the built-in buttons plus a couple of labelled ones (those 'arrows' are really unicode characters, I may change them to prettier images at some point.)
Thank you in advance. :-)

Resize UIImage/UIImageView without keeping aspect ratio

I have a UIImageView that I've added a PinchGestureRecognizer to. Currently, the image is resized nicely when pinching, but I want to be able to resize the image without maintaining the aspect ratio. So if the user pinches horizontally, the image view's width would enlarge; if they pinch vertically, the height would enlarge and so forth.
Can anyone give me a hint on how I could do that please?
Write a custom gesture recognizer that requires two fingers to be on screen.
Once both fingers are on screen store their offset to the imageView's border in some UIEdgeInsets.
In touchesMoved, check if both fingers are onscreen: if so, calculate the new frame by applying the edgeInsets in the current touch position.
Header: click
Implementation: click
Works well and feels more natural than other implementations I've seen.
You would need to do the touch handling yourself as UIPinchGestureRecognizer only supports one scale which has no concept of being pinched horizontally or vertically.
You could create your own subclass of UIGestureRecognizer (see here for docs) which looked at the horizontal and vertical separation of the touch points to determine 2 different scales. It should be fairly straightforward to create I would have thought. Just look at the initial touch points and then when they move, calculate the difference in the current separation of the touches to the initial separation of the touches, in both the vertical and horizontal directions.

What's the RIGHT way to draw an image in the upper left corner on a mac?

I have an NSView in a ScrollView and I'm trying to draw an image in it. The problem is that I want the upper left corner of the image locked to the upper left corner of the frame, instead of the lower left corner, which is what the View wants me to do. I will need to be able to zoom in and out, and rotate.
currently, I have a kludge of a system where I calculate how much I have to translate my image based on the size of the image and the size of the window. In order to do this, I needed to create an extra view outside the scrollview, so that I could get the size of the window, not including decorations. Then I can calculate the size of the view based on the size of the image and the size of the window, and based on THAT, I can figure out where to translate the image to.
My only other thought was to use the isFlipped: method, but that ends up reversing my image L-R which is bad.
Is there another way I should be doing this?
If you want 0,0 to be in the upper-left corner, then overriding -isFlipped to return YES is the way to go. It should not affect the coordinate systems of any subviews (I think!), but images drawn directly into the flipped view will appear upside-down unless you apply a transform to them.
View Programming Guide for Cocoa: View Geometry