Initially unscrollable scrollView? - ios

Because I have a scroll view, I have set my View Controller to freeform with a fixed size (since that was what I learnt). I want to have my scroll view such that it starts with the same contentSize and scrollable size (so that initially you can't scroll), then later after buttons are pressed the scrollable height increases so that you can scroll. I had tested all this on the iPhone Xr model simulator, and it was all working well until I tried switching to a different iPhone model (iPhone 7+). When I tested my program with the 7+ (which is shorter in height), the scrollView was initially scrollable (which it wasn't supposed to), and I think it might be because I have set my View Controller to freeform with a fixed size (which fits the iPhone Xr model which is taller), so when I try using a smaller iPhone model, it still has the same bigger length so it initially is scrollable.
What I want to get is have my scrollView go from the top of the screen of the iPhone to about halfway, x above a button I have. What I had initially was:
scrollView.contentSize.height = 404
Which I now know is completely wrong since I was hard coding it, but I don't know how else I can find the height from the top of the iPhone screen to the button. Perhaps its something along the lines of:
scrollView.contentSize.height = button.frame.origin.y - /*y position of top of iPhone screen*/
I also considered that the height of the scrollView might just be the y position of the button, however, because I have a fixed View Controller height, for iPhones with smaller displays, that would make the scrollView much larger than what I want (a size such that you initially can't scroll).
Hopefully this makes sense, thanks.

How to get the screen size:
let screenFrame = UIScreen.main.bounds // returns a CGRect
let screenHeight = screenFrame.height // returns a CGFloat
Edit: If you are trying to go completely using storyboard, try setting required constraints from the scrollView to the view to get it where you want.
The height of the contentView inside the scrollView can then be set equal to the height of the scrollView, but with a low priority.
I think that should work, though it's easier to explain when starting from scratch. Let me know how it goes.

Related

How to fit a "freeform" UIViewController to multiple screen sizes?

I have created several freeform UIViewControllers that have extra long heights for scrolling purposes, and widths that equal the width of an iPhone 8 Plus screen (because that's the physical device I have available for testing with).
My problem comes when I am trying to make my app functional on all devices down to an iPhone SE sized screen. The height isn't an issue, but the width is creating a problem because on smaller screen sizes.
UIViewController is obviously wider than the screen. so, it allows for horizontal scrolling/panning. However, my goal is to have the ViewController match the width of the screen being used. so, only vertical scrolling is possible.
I've tried to adjust the width of the UIViewController when it gets presented, but that seems to have no effect. I'm really not sure what else to try and can't find anything about this online. Is this an obvious fix or am I doing something completely wrong?
To properly answer this question and for other people that might be having this issue.
The view controller size automatically adjusts to the screen size (provided its properly configured).
If you have an scrollview inside a view controller, then you should make sure the edges of the scrollview are attach to its parent view (the view controller's root view) using auto layout constraints.
In addition, the scrollview contents must be set to use the root view as the position reference (at least horizontally) otherwise auto layout won't know how to handle the horizontal positioning.
To accomplish this you just need to attach the inner view (that fills your entire scrollview) to the left and right edge of the view controller's root view as well.
I think you might be mistaking your UIViewController with a view. If your view is a scroll view, you can set the content size of the scroll view to be the same as the width of your device and it should achieve the desired effect.
In Swift 3.0 and above:
let screenWidth = UIScreen.main.bounds.width
yourScrollView.contentSize.width = screenWidth
To support multiple widths you can use different size classes available in iOS.
there are many tutorials available for size-class related constraints.
like https://www.bignerdranch.com/blog/designing-for-size-classes-in-ios/,
https://www.bignerdranch.com/blog/designing-for-size-classes-in-ios/
you should have to give View's constraints in relation to their Parent views if possible for your design.
I've tried to adjust the width of the UIViewController when it gets presented
By "presenting" you mean viewDidLoad method? I don't think it's the best place to adjust width because at this moment view bounds are not yet known. Besides viewDidLoad method is not called when devices is rotated.
I suppose you should update scroll view width in viewDidLayoutSubviews which is called every time when root view bounds changed in view controller:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let screenWidth = UIScreen.main.bounds.width
yourScrollView.contentSize.width = screenWidth
// I don't think you really need it
// but it may help
yourScrollView.setNeedsLayout()
}

ContentSize Height of UIScrollView in iPhone X not updating

This issue sounds easy at first but this is one of those things that I had to ask a question for suggestions since there is no other way I can think of to solve this. I already searched too far for solutions but did not find any.
Situation
I have a collection view that scrolls horizontally that covers the whole screen.
I added a scroll view inside each cell's content view that contains several views that will be taller than screen height.
After the last subview is added I update scroll view content size using:
scrollview.contentSize = CGSize.init(width: screenWidth, height: (scrollview.subviews.last?.frame.origin.y)! + (scrollview.subviews.last?.frame.size.height)!)
Let's say "scrollview" is the scroll view and "screenWidth" is the width of the screen. It works on other devices except iPhone X will scroll maybe for two screen heights worth but that's it. Other devices can go to the bottom of the scroll view.
While writing this I thought:
what if I need to add top and bottom padding of safe area to content size height since it extends there.
I did it but it only added so little and a big part of views still cannot be seen due to this issue.
Inputs are welcomed. Thanks in advance.

ios autolayout issue on smaller screen

Originally I am working off of a view of size 4.7 inches in my storyboard and laying out everything from there, however I'm running an issue when running the app on a smaller screen.
The view in question is a view with a scrollview inside of it and a bunch of labels and text fields inside that. When running on the iPhone 4s for example, or even the 5, the scrollview appeared to be pinned at the bottom and I was wondering why, I had tried playing around with insets and offsets but nothing worked.
Looking at my storyboard, when I switched the fixed size of the view to 3.5 inches, it looked like all my top elements were outside of the view altogether.
I'm not exactly sure how to go about this situation.
Any help would be appreciated.
Can't help too much without more information but it sounds like you don't have constraints set properly. You should have constraints set for the scrollview to match the views size and be centered as well the labels have constraints to the scrollview, other wise when the screen sizes change there will be issues. When working in storyboards you should try using the inferred size instead of a certain screen size, that way you don't try to design the interface for a certain screen size.
In code you could do something like this to set proper constraints
scrollView.frame = view.frame //Or I could set the height, width, center contraints
label.translatesAutoresizingMaskIntoConstraints = false
label.centerXAnchor.constraintEqualToAnchor(scrollView.centerXAnchor).active = true
I would try to help with the storyboards but I would need a little more info. I tend to do my constraints in code.

In Swift, how to determine the physical size of a device screen?

I am adding views programatically. For example, I have a scrollView as a top-bar menu, I set its height to 60. (I am already using auto layout for placing these views)
This top-bar menu looks alright visually in an iPad. However, in an iPhone, it's kind of occupying too much space. Therefore, I am thinking to change the height to 45 for an iPhone.
What's the way to get the physical size of the screen? (not screen resolution) So I can make the height proportional to the physical size?
You can get this information accessing UIScreen singleton.
To get size use UIScreen.main.nativeBounds. Also you can get scale coefficient of screen UIScreen.main.nativeScale.
You may want to consider working with the frame property of the view of the current view controller.
self.view.frame.size.height and self.view.frame.size.width
You can make your other views proportional to those dimensions or based on their values, etc.
This code should adjust your scroll view to the size of the users screen.
self.view.frame.size.height and self.view.frame.size.width
Also, make sure that your constraints are all good.
Use view.frame.size.height and view.frame.size.width to determine the size of different screen sizes. This will work inside functions only.

How to calculate UIImageView size?

I have a Swift app which sets a UIImageView to the size of a portion of the screen (set with autoconstraints to the margins and controls above it), and I use the height and width values of the ImageView to create 3 additional UIImageViews programmatically and position them on top of the original image. I am constructing a podium and place three images on top of the podium in appropriate positions. I then calculate the height and width of each additional image by creating a constant: let conImageHeight = 0.4 * self.imgPodium.frame.height. However, I can't get a reliable height and width of the original image.
Initially I used self.imgPodium.bounds.height which worked great for the iPhone 6 simulator screen size, but when I tried running the app on an iPad simulator, it kept the iPhone size values. The image itself changed size but when I println() the height and width using bounds, I get the values of the iPhone image.
I then changed and used self.imgPodium.frame.height but this didn't change anything.
Is there a better way to get the height and width of a UIImageView (or any control for that matter) after it positions itself through autoconstraints?
Thanks.
Questions I've looked at already but didn't help:
Change UIImageView size and position programmatically in Swift
how to check screen size of iphone 4 and iphone 5 programmatically in swift
UIImageView Bounds, Frame
Cocoa: What's the difference between the frame and the bounds?
How to resize an UIImageView (swift)
In viewDidLoad the subviews have been loaded and initialized but not layed out yet. Therefore their frame property for example is not valid yet and may be the one that was set in Xcode when designing the UI in the first place - that however is not reliable. You should do custom layout in places where you can be sure the layout has already happened yet: e.g in viewWillLayoutSubviews or viewDidLayoutSubviews. Both methods will also get called when the layout somehow needs to change. In viewDidAppear the layout has been done yet and therefore you can do some layouting too. This code however will get not get called when the layout changes due to interface rotation for example. AND it will get called after a presented viewController gets dismissed again. (not what you would want).
In both cases: do your setup of creating new imageViews in viewDidLoad and do the layout in viewWillLayoutSubviews or viewDidLayoutSubviews!

Resources