UIScrollView setContentSize breaks view with Auto Layout - iphone

I am using Auto Layout in my iPhone app and have a UIScrollView. I need to change the content size of my scroll view at several points while my apps running (so setting the content size in viewWillAppear is useless as I have seen this suggested in other places).
When I change it, my subviews jump about, presumably because it breaks the auto layout constraints.
So how can I approach changing my scrollview content size with auto layout enabled?
Thanks.

I was having this same issue, and I know this can't be the final solution, but for now, rather than calling this in viewWillLayoutSubviews, by putting the code inside viewDidLayoutSubviews it allowed me to set the contentSize AFTER the viewController did it's default business :)
Hope that helps.

Test your code in viewWillLayoutSubviews. Apple say:
When a view’s bounds change, the view adjusts the position of its
subviews. Your view controller can override this method to make
changes before the view lays out its subviews. The default
implementation of this method does nothing.
UIViewController Class Reference

Related

Subviews size issue - UIView related sizing in xib

For a layout made of some views stacked in each other, which are all subviews of the UIView and I wanted to know how to automatically size the main UIView which may be multiline once the app is live and updates come in. UIView width is fixed.
I believe the view (UIView) does size itself so i dont think you will face this issue. Just try to not constrain the height and make sure you select appropriate stack view while doing this since you got multiple. Hope this helps as i assume that you are not using collection view for this matter!

UIScrollView Controller not scrolling fully

I am pretty sure this has something to do with the dreaded AutoLayout. (been trying since 2days to get hang of it)
So I mastered it somewhat, but now I have problem where my UIScrollView is not scrolling fully down, pictures are much better at explaining these things
this is the scroll view
this is the content view
so the problem is the scrolling is happening but then again it springs back up. So I am not able to click on the signup button
EDIt 1
Edit:
I have created a little example on github for you to look at, here. The project illustrates the answer below and uses the techniques I describe and nothing else.
Original Answer:
couple of things I would advise here.
First, I know you've been trying for a while but remove all the current constraints (painful I know but). Do this for clarity as ....
The view should be the size of the scene, it looks like you want the scrollview to be the full screen so that too needs to be the size of the scene.
e.g. if you are designing at 6Plus by default the scene size is 414x736 so the view and the scrollview it contains should also be 414x736.
Only the content view needs to be the size of the real content you wish to show. Let's say for arguments sake that the content is 414x1000.
Now the constraints for the scrollview are simple. It needs zero spacing to all it's edges.
You can add the content view to the scrollview in a couple of ways. The way I try to do this varies from project to project and depends mostly on how complex the scene is. If it's a really busy scene I keep the content view outside of the scrollview in interface builder so that I can work on it easily and visualize the whole of the view. Then I add the content view to the scrollview in code.
If its a simpler view You can add it inside the scrollview in interface builder. Ultimately whichever way you do it, you can lose visibility of the content view in interface builder because the contentview is larger than the scrollview and the content gets obscured. So play about and find a good way for you.
Define the content view and all it's subviews. The content view needs to be taller than the scrollview otherwise it wont scroll. All of the content view's subviews need to have defined heights from top to bottom and widths from left to right. In your case the scrollview is scrolling vertically not horizontally so all the widths need to add up to the width of the scroll view BUT the heights need to add up to the full height of the content view.
Note: if you do this proportially your life will be easier later. If you do all this with fixed heights the storyboard will break on different device sizes.
Now the "tricky bit" and it's a bit counter intuitive. You need to pin the content view to the scrollview, remember the height of the content view is taller than the scrollview. In all other circumstances in Interface Builder pinning a view to a superview (0 padding) will adjust the height (or width) accordingly. For the relationship between a scrollview and it's content view this doesn't happen.
First pin the contentview
Notice the -400? Remember the content view is taller than the scrollview and we will change this immediately.
Select the bottom constraint (-400) that we have just created:
Select the drop down arrow next to the constant value:
Select Standard Value and type in 0 for the constant.
You should now have a storyboard with no broken constraints and if you build and run you should get a scrollview as desired.
Your bottomspace to superview on your content view is set to -74.0, I don't know if there is a reason you had to do that, but try setting it to -8.0. I think your scroll view is scrolling up to the 0.0 mark automatically

UITextView inside UIScrollView scroll problem

I'm experiencing something considered a bug in my situation. Probably this is not a bug but a feature ;).
Here's my case:
I load a UIScrollView with my content. A part of my content is loaded asynchrone after the view is already loaded. This works great and without issue.
Some of these controls however are UITextView controls. Once I set the content (text property) of these controls after the viewDidLoad my UIScrollView scrolls down to the last UITextView that was set. I want to prevent this and want the UIScrollView to maintain it's top scrolled position.
In summary:
If I set the Text property in the viewDidLoad method no scroll occurs. If I set the Text property on the UITextView after the viewDidLoad method (because I load the data asynchronous) the UIScrollView will scroll to the last UITextView that was set. I want to prevent this scroll.
How do I achieve this ? I have a feeling this is just a property which is set wrong but I can't seem to find it.
Thanks in advance.
EDIT:
I've tried setting the "scrollEnabled" property to NO before setting the values and to YES after but this didn't have any effect. The ScrollView will still scroll when the text property of the UITextView is set.
I Fixed the issue with a work-around:
I set the scroll view content size to something small, like 320 x 300 or whatever the height of the scrollview frame is, then did my work, then put the content size back to normal.
This prevents the scrolling while the data is loaded and enables it as soon as the loading is finished.
This would not change the scrolling problem but maybe make it "hidden" for the user:
yourTextView.text = #"Eat more bananas!";
yourScrollView.contentOffset = CGPointMake(0.0, 0.0);
Some snippets of your code would help to face the problem more specific.
EDIT:
Or try to add the UITextViews to a UIView, then add the UIView to the UIScrollView. Make sure that the UIScrollView's contentSize is the same as the Size of the UIView.
This worked for me too :p but i had to set the height to something less then 300 (in my case i just used 10).
Basically the idea is to make the text view not part of the visible area of the UIScrollView wile you are changing the text of th UITextView.

iPhone: How can I turn a flipside view into a scrolling UIScroll view?

This should be simple.
I'm making a very basic app, based on the Utility Application template of XCode.
On the flipside, I have more content than fits the screen.
The flipside is a UIView. I think it should be a UIScrollView, but somehow I don't get it to work.
Can anybody here advise me on this?
With a UIScrollView it is not enough just to place the control into Interface Builder and place the items within it; you have to set its content size in code.
Therefore in the -viewWillAppear method (or similar) you should have something like:
[scrollView setContentSize:CGSizeMake(320, 600];
This would make the content size inside the scroll view 600 pixels high (ie larger than the height of your iPhone display). If everything else is wired up correctly, this shoud now work.
Note: You may also then need to reposition your objects within the view. Set frame.origin for the objects that require this...

Laying out & sizing of subviews in a UIViewController

I have an app with with a UITabController and each tab is a UINavigationController. The root of one of my UINavigationControllers is a UIViewController.
Inside that view controller's view, I want to layout some subviews, but I'm confused as to where & how to lay them out in a way that will be resolution independent (i.e. not hardcode values such as 320px, 480px, 44px, etc.).
When the view is fully loaded and presented on a vertical iPhone, it's height will be 367px = 480 - 20 (status bar) - 44 (nav bar) - 49 (tab bar).
Inside the view controller, I currently create all my subviews within the viewDidLoad method. However, it appears that within this method, the view's current height is 460px (self.view.bounds.size.height). So when setting up my subviews, I cannot properly calculate the sizes of anything.
Within the viewWillAppear: method, the view does know it's proper size, but that would mean setting & calculating the subview's frames every time the view will appear (e.g. tab changes or popping from child view controllers on the navigation stack.
Is the only way to do this properly to layout in viewWillAppear:?
I have tried using the autoresizing properties (parent's autoresizesSubviews & autoresizingMask) but they don't seem to work at all!? Do these only take effect once the view is all setup and then it is resized (manually / orientation change?).
I'd be grateful if someone could let me know why the autoresizing isn't working, and how best to lay things out by not hardcoding any sizes.
You can do your layout logic inside the viewWillLayoutSubviews of the UIViewController.
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
// Your layout logic here
}
DOC: Called just before the view controller's view's layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop.
autoresizesSubviews should be set on your parent view, while autoresizingMask should be set on the child views - this is the mistake I made so you could, too.
In loadView you should size your subviews to fit whatever size of parent view is at the moment, and then later on when parent view is resized from 460 to 367 pixels your sub-views will be resized as well, according to your mask settings above.
If that fails, there is nothing wrong in setting the view size within viewWillAppear - the performance impact of doing it every time is negligible.
If nothing else works, there is always layoutSubviews: - there you could do manual layout if you have to, it's invoked when system believes layout may have to change. there is also setNeedsLayout: that I sometimes invoke from viewWillRotate:/viewDidRotate: etc. But really this shouldn't be needed and autoresize should be good enough.
EDIT: Yes, to implement custom layout logic in layoutSubviews as I mention above one would need to subclass UIView.
Swift 5:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// Your Code
}