Trying to set a wide image in UIScrollview, with a fixed height - swift

Novice that has been stuck on this problem for 2 days (please help!). I have an image that is much wider than the screen. I want the user to be able to scroll horizontally on the Image, and also want the image to be a specific height while maintaining it's aspect ratio.
Currently the UIImageView is nested within the ScrollView. The ScrollView has constraints to the Safe Area in all 4 directions, that place it in the upper half of the screen (250 from the bottom of the Safe Area). The ImageView has all 4 constraints of 0 to the "Content Layout Guide" of the Scrollview, and a 5th constraint of having an equal height to the "Frame Layout Guide" of the ScrollView.
I initially tried to set the image Content Mode to "Aspect Fit". This maintained the aspect ratio and set the image with the desired height within the ScrollView, however left a huge amount of transparency either side of the image so the user has to scroll for a while before seeing the image. For this I could not find a solution that contained the scrollview within the bounds of the non-transparent section only, so I then changed the image Content Mode to "Aspect Fill".
This removed the transparency either side but the image is now too tall and goes off the screen vertically. I have set "Clip to bounds" on the ImageView Size Inspector and also set it to true in code, but the image is still to tall and outside the height constraint specified. I also used:
gym_imageView.sizeToFit()
scrollView.contentSize = gym_imageView.frame.size
But none of this is fixing it.
My expected result was that the image with original dimensions (W: 12064px, H: 1696px)
Would resize itself to the constraint height (0 to top & bottom of Content Layout Guide of Scrollview, which in turn is constraint 0 to top of Safe Area, 250+ to bottom of Safe Area) while maintaining aspect ratio.
Any ideas?

The Content Mode changes how the image appears in the imageView, but it does nothing to resize the imageView itself.
You should set an explicit aspect ratio constraint on your imageView with a multiplier of 12064:1696. Then Auto Layout will be able to calculate the correct width of your imageView based upon the fact that it already knows the desired height.

Related

Swift - How to make a StackView 100% width

Im trying to create a profile screen for an App. The only element that i cant get the width set dynamically is a 3 x 1 button grid in a stackview.
You can see in the second screenshot how it resizes rather than dynamically resize like every other element
This is my approach. I made stack view which trailing and leading constraints are 0 and image height is set to 30 with aspect ratio 1:1 (this can be customized). Each image has its own View where its centered and then stack view aligment is set to center and distribution to fill equally. This can be used for buttons too.

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

UIStackView in storyboard forces intrinsic content size

In storyboard I have added a UIStackView to a UIView and inside the UIStackView I've added a UIImageView with an image specified. The image specified is in XCAssets and has a 2X size of 59X60. The UIImageView is getting its width set to this intrinsic size but I want it to be 44X44 and the image to scale to fit. However in Storyboard with and Height settings are disabled and set to 59X60 for the ImageView and for the UIStackView as well. I want to have 5 of these same ImageViews with stars stack horizontally at 44X44 inside the UIStackView.
Ideas?
Update: It seems that adding a height constraint to the UIStackView will cause the scaling but the star is then distorted in appearance.
The width and height fields are grayed out because the image view is inside a stack view. You must use constraints to control the size of a stack view's arranged subviews.
First, make sure all five star views have “Content Mode” set to “Aspect Fit”:
Then, constrain all five star views to have equal width and height to each other:
Finally, constrain one of the star views to have a constant width of 44 and a constant height of 44:
If you want space between the stars, set the “Spacing” of the stack view:
If you want padding around the stars, you can do that outside the stack view, or you can set the stack view's “Layout Margins” to fixed constants (and turn off “Safe Area Relative Margins”):

Making ImageView Depend on Image Size But not Fixed ImabeView

I want to make a dynamic imageView which can depend on the image ratio inside(image's ratio different).
And the imageView width follow the screen width(or the tableView width), image's height is resize by the image inside.
My storyboard looks like that:
The imageView mode set Aspect Fit.
How can the image's width be the same with tableView(or screen width)?
And to resize both the height of the image and tableView ??(don't leave yellow margin)
Don't fix the height and width of imageView.
Using constraints just set the x, y position, it automatically becomes resizable according to image size.
I suggest you add a Y constraint, e.g. use the pin board to constraint the vertical spacing to top layout guide, and then use control drag to the view controller icon, to centre the imageView horizontally, then when you set the image for the imageView, it should automatically resize to the size that the image is as you won't have set any size or aspect ratio constraints. If you wanted, you could set a constraint to say you always want it to be an equal height from the table view, however, this could cause the image to look stretched if you do not set the aspect ratio.

UIScrollView Causing "Misplaced Views" AutoLayout issues

I'm running into a strange AutoLayout related issue when I use a UIScrollView (the issue does not occur without it).
I have a UIScrollView that is constrained to the boundaries of a UIView (contained within a UIViewController), and within that, I am attempting to place a UILabel and UITextField side by side. I have constrained the UILabel to the left and upper boundaries, with it's width and height constrained (see screenshot below):
Right next to this UILabel is a UITextField, which is constrained to the left, top, and right, as well as having the height constrained. However, this results in a "Misplaced Views" warning, that states "Expected width = 163, Actual width = 413", shown in the screenshot below:
When I choose to "Reset to Suggested Constraints", the "Misplaced Views" issue disappears, but in it's place I am left with a width constraint of 413 points, which is something I'm hoping to avoid, as I would not like this UIViewController to be horizontally scrollable on smaller devices.
A scroll view has a size (the size it takes up on the screen) and a content size (the size of the entire scrollable area). In Auto Layout, the content size is automatically computed from the constraints of the items in the scroll view. This is a problem, because you are trying to make the scroll view have the same width as your screen, and then have the items constrained to that. When you do that, Auto Layout insists that you give your text field an explicit width so that it can calculate the width of your scrollable area.
To do what you want, do the following:
Add a "content view" to your scroll view. This view will be the only top level item in your scroll view. It will hold all of your content as subviews of it. Drag out a UIView and add it to your scroll view. Constrain its top, leading, bottom, and trailing edges to the scroll view. Constrain its width to the width of the scroll view. Give it a height constraint and set it however big you want your content area to be.
Add all of your labels and textfields to this content view. Now you can constrain them centered in your content view or constrained to the edges, and it will work as you want.