Is it possible to set autosizing in interface builder for rotatable bg image? - iphone

I'm designing the UI with IB with a lot of images, and the default design orientation is landscape. However, I need to shrink the whole view to fit in portrait mode, by shrinking to the maximum allowed width and maintaining same aspect ratio for the view with it's inner images. The best way to imagine what I want to achieve is to imagine some landscape photo. When you rotate that to portrait it shrinks to the maximum width, centers vertically, but maintains the same aspect ratio. In my case, I want to shrink a view with its all inner subviews.
First, I'm manually resizing view frame to required size in viewWillApppear, and also calling setAutoresizesSubviews to resize all it's inner views. Those inner views - images are with "Aspect Fit" and all autosizing options set (to fill the available area on resized view). However, inner views pops out of the container: some images jumps to the top, text view expands to full portrait height. Is possible to set some kind of "view-container", then say - "view resize to size X and resize all your but only inside view-container area?

When you design in IB you must check several things. First of all the "view container" properties, that is the view that contains all subview. In order to behave properly on rotation this view must be setup with right IB Autosizing properties, that is with the autosize lines (springs) and border lines (structs) correctly set. In your case you want your container to be exactly fit with the main view so enable the "structs" at the four sides and enable the "springs" inside. Play with this values and look at the "Example" displayed by IB.
Then you must instruct this container to properly behave with its subviews. So check in IB that "Autoresize subviews" and the content mode, if needed, (= "Mode") has the wished setting.
At this point you check in the device or the simulator if your view is rotating and rising properly.
Then you must take care of the content of this view, which is a UIImageView. This must be centered, so remove the structs, and autoresized, so set the springs. Then set the content mode to Aspect Fit or Aspect Fill at your wish.
These settings should work. For more complex stuff, you must programmatically set things.

Related

Trying to resize my UIView containers to fit smaller iPhone screen sizes

I am trying to have my layout fit on multiple iPhone screen sizes, but I am having trouble resizing my UIView's to resize themselves when on screen sizes smaller than the iPhone xr.
I have constrained the views, labels, and buttons properly and everything is aligned, but when viewing the app on smaller screen size, I don't fully understand how to resize my UIView containers to resize themselves to fit smaller screens.
On smaller screens, my button does not show up because the screen size is too small. The UIView's are the issue and the stack views inside them also need to resize or shrink the text to fit everything on the screen.
Image of my storyboard, and respective screen sizes
"I don't fully understand how to resize my UIView containers to resize themselves to fit smaller screens." -UIViews won't resize according to the screen, you will have to add constraint for them so that they pick their width and height. Alternatively you have to set constraint for fixed height and width.
In my opinion, for supporting smaller screen size, you must use scrollviews as parentview. So that user can scroll in the app. Also you can give relative width and height for views inside scrollview.
Scrollviews are required because you will always want some minimum width and height for buttons, labels etc. Otherwise on larger screen like Ipad they will be very large, while on smaller screens they will be very small.
You can use TPKeyboardAvoidingScrollView: How to use TPKeyboardAvoidingScrollView, or just google for that. It handles keyboard showing and hiding task, which is a headache otherwise.
Here is how I think you can solve your issue:
Set Some minimum height and width for your topmost view(scrollview preferably).
Now add other views inside it and use relative width and height. In relative width and height you give values in ratios. Here you can get an idea how to do that: -Giving width in % values in autolayout.
Also add additional constraint on your internal views for minimum height and width so they don't fall below certain size.
I would not suggest, but you may always use UIScreen.main.bounds.size.width and UIScreen.main.bounds.size.height to get the width and height of screen. And according set values for your constraints in your view/controller class. Here is a link for setting value of constraint in swift class:
set contraint value programatically

How to perform an interactive animation with Auto Layout in which you interpolate between different constraints?

I'd like to have an interactive animation where a view transitions from one set of constraints to another as the user drags up/down the screen. The background image should shrink vertically (easy), and the profile image should change from being horizontally and vertically aligned to the background image to being anchored to the top and left corners of the background image. Is this possible?
Yes, it is possible, and you can see this effect in the Avvo app, for example (in the lawyer profile screen). The trick here is to smoothly transition from one set of constraints to another.
Here's an outline of how to do this:
add a UIScrollView. Add the view you want to animate as a subview to the scroll view.
Make your view controller implement
UIScrollViewDelegate
In the delegate method
scrollViewDidScroll(_:), update the constraints' constants as
needed.
Also in that method, when contentOffset crosses a
threshold value, flip to a different set of constraints, by setting
their active property to true or false.
To keep the view (the headshot image, in my example), pinned to the top as you scroll, just continuously update its top spacing constraints based on the contentOffset.y value.
Achieving a perfectly smooth transition may take some trial and error, but it definitely can be done!
Here are the screenshots showing the transition as you scroll up:

iOS: how to adjust positions of UI elements one by one properly by IB when some of them may change size?

For example, on a UIView, from left to right there are three buttons:,button1,button2,button3.
When button 1 become wider, such as its width become twice as its original width, is there any interface builder way that can make button2&3 move right automatically?
sorry for I didn't make my question clear.
I mean such kind of size change: I push button1, then I change it's frame in my code, not caused by the change of text in butotn1. I want button2&3 to move right automatically, keeping the width of the gap between button 1 and 2 unchanged.
Thanks everyone.
IB can be used only for initional positioning of views.
True, you can also define autoresizing masks of the views but that's about it.
Any additional laying out should be done in code.
I could be wrong, but I don't know of any way you can do this in IB. It's pretty straight forward in code though, just link the buttons to some IBOutlets and check the sizes of the images of the buttons (myUIImage.size), then adjust the frames of the buttons (do it in viewWillAppear).
Seen your edit - if you're adjusting its size using code, adjust its position too.
If your buttons are in a row at the bottom of the screen, consider using a UIToolBar. Its UIBarButtonItem objects automatically adjust to fit each other's width changes. For more generic cases, you'll need to recalculate positions and sizes as in Franklyn Weber's answer.
Yes - by using autoresizing masks. If you allow the margins to be flexible (no red lines connecting the frame to the superview's frame) and allow flexible width and height, the buttons will size and move proportionally.

Rotating UIView and background to landscape mode

The initial root view controller is 9 (3x3) buttons with a custom background in portrait mode. When the device is rotated into landscape mode the last row of buttons (of course) are cut off and the background (which is 320x480) doesn't fill the width of the screen.
What is the proper way of handling this? Do I need to move and resize the buttons myself? Do I have multiple Nibs? How do I resize/rotate the background?
Use shouldAutorotateToInterfaceOrientation and/or deviceDidRotateSelector in your viewController to reposition / layout & scale your views programmatically as you require.
If you set the auto-resizing masks on the buttons to have flexible margins in all directions they should reposition themselves appropriately when you rotate the device. You can do this either in code, or in Interface Builder (which has a nice little simulator demonstrating the effect)
With regards the background, what I prefer to do is to make the image the combination of the maximum proportions of each orientation, and then center it. For instance, make your image 480 x 480, make the view that houses it the same size and then use the appropriate auto-resizing masks to achieve the desired effect.

how do i work on a taller view in interface builder?

OK, so I am learning to use UIScrollView in interface builder. since the scrollView itself does not have any content, I created another view, the contentView, to hold my controls and scrollable content. into this view I place controls, labels, etc and then in my code i set the contentSize of the scrollView to the size of this contentView.
My question seems stunningly simple and so obvious that I must have missed something somewhere. when I created this XIB in IB I got your standard empty iPhone interface window. I dropped a scrollView on top of it, it took up the whole window. I dropped a view on top of that, it took up the whole scrollview. I added some controls, which so far I can still see inside the contentView rectangle in IB.
My question is how do I work on/add controls which lie outside of the visible part of the contentView in IB? LOL. it seems so simple, but i just don't get it. I can set the height of the content view or drag the rectangle to whatever I like (and indeed this is the whole point of having a scrollview) but the fixed UI window from IB won't expand so i can see the "offscreen" part of the contentView to add more controls. It's like it's just fixed at that size because that's the size of one iPhone screen and it won't let me make it any bigger/taller.
what did I do wrong?
-a
You need to turn off all simulated user interface elements (like the status bar) to be "undefined" except for size, which you select to be "Freeform" from the drop-down, and then you can set the view height using the Ruler tab to be whatever you like.
For example, here I've selected a photo view controller, and set the size in the right side bar to be "iPad Full Screen" - but I could also change that to "freeform" to set any height I wished.
First add a ViewController by any which way you prefer. Then in interface builder, click on the view controller Icon (on left). In the connections inspector click on the ruler icon "Show the size inspector". There will be option list for simulated size, change to "Freeform" and increase the height to any size you want. Hope this helps.
neeever mind. you drag the content view up so that some controls are offscreen and then add more controls/expand to the part you just made visible by moving the top stuff off the top. in effect, you physically scroll the contentView in IB by dragging it with the mouse. seems a smidge counterintuitive, but whatever.
Set simulated size to freeform for the the view controller to a large enough size that you can add in your controls
You don't have to create a view to place inside the scrollview if you don't want. In your case, it sounds like it doesn't make much sense.
As for the second part of your question, you can place items directly on the scrollview (it is a view afterall), as subviews. If you want them to be off screen, then just set their frame up to be at those particular x, y coordinates you want it to be at. You will have to ensure your scrollview's contentSize property is large enough though to house your entire content, this is what allows scrolling horizontally/vertically.
You probably want to do the offscreen elements programmaticly instead of using xibs.