UITableView contentOffset for headerView misaligned - ios

My headerView in my tableView should go all the way to the top of the device. On iPhone X the same so the notch goes over it.
Then when I scroll my tableView I use scrollViewDidScroll(scrollView: UIScrollView) to change the height of my headerView to add scrollView.contentOffset.y so it goes all the way.
It works as soon as I scroll but not initially.
So it looks like this:
and this on the X
How to I get rid of the white area so the grey one goes under it when it loads?
I tried a couple places but it seems the tableView still has no contentOffsets... I think I am missing something fundamental here how "it should be done"...
Update: ViewHierarchy, blue is tablewView, but then I get this distance there...

Ok I found it. So it has to do with the change with safe areas introduced for the iPhone X.
There are two possibilities, it really depends on the storyboard setup:
If you are using a storyboard and your base is a UIViewController with a tableView placed inside it:
Then fixing the auto layout is the answer:
When safe area is enabled, click on your topmost view and create the top constraint is relative to the superView with constant 0. By default it wants to protect the safe area so it is set relative to the safe area.
If you are using a UITableViewController template (e.g. default when dragging out a navigation controller - tableview combo (my case))
Here there are no constraints that can be set. Hence it didn't work for me (see above).
To fix it click on the root tableView, select the size inspector and then set "content insets" to "never".
Or programmatically in viewDidLoad:
self.tableView.contentInsetAdjustmentBehavior = .never

Are you making your tableview in storyboard?
in viewDidLoad try anchoring your tableview:
tableview.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

Related

UIModalPresentationPopover - arrow direction Up, Prevent Contentview from starting from tip of the arrow

in iOS 13 it happens that the view of UIViewcontroller that is presented as model starts from the tip of the arrow. Because of it top banners in all of my popover gets cut. Can I prevent this from happening ? I want that my UIView does not start from arrow but once arrow is finished.
To fix this issue, I opened up my view controller's XIB, selected the top-most view, and then checked "Use Safe Area Layout Guides" under the File Inspector. Then I added Auto Layout constraints (of length 0) around that view's sole subview (a UITableView).
(I also needed to update the view controller's background colour. This changed the arrow colour back to what it was in iOS 12 and before.)
Background: https://forums.developer.apple.com/thread/122703
I wonder if your contentView contains UIScrollView. If yes, please add alwaysBounceVertical = YES to your scrollView. It works in my case.
I don't know why they changed this behavior, it can be a pita to deal with it if you are not using xibs. I couldn't find anything in the docs about it.
Use the safe areas to adjust the position of your view. You can both try to extend the size of that red area, or skip the arrow completely. In this particular case you can use safeAreaInsets.top if the arrow is going to be on the top always.

Convert view to scrollview for modal controller

I have some modal controllers that are UIViews and are not scrolling.
Reading on SO, the apple docs and elsewhere, it seems there are three approaches to fixing this:
Multiselect all the elements within the view and then go
editor-embedin-UIScrollview.
change the view to a scrollview in the identity inspector and then
add the following line to viewdidload:
[(UIScrollView *)self.view setContentSize:CGSizeMake(320, 2000)];
Copy elements to clipboard, delete the uiview, add a new scrollview
and copy the elements into the scrollview. Warning - this destroys
the positioning of the elements although it does preserve their
outlet properties.
However, I have tried all of these and the scrollview still does not scroll.
Is there any other step I am missing?
Thanks in advance for any suggestions.
Edit:
Getting scrollviews to work is not easy and there is much conflicting advice on the web.
I finally got this to work by setting the content size in a separate method as opposed to viewdidload.
(void)viewDidLayoutSubviews {
self.MainScroll.contentSize = CGSizeMake(320, 1800);
}
Thanks as well to Evo for advice on setting all the vertical dimensions correctly and using freeform in the VC size inspector as it won't work if you don't carefully set these.
If you have EVER enabled autolayout, even if it's disabled now, you need to:
Select the view controller you plan on scrolling
At the bottom right of the storyboard view, click the third button (far right) and then "Reset to Suggested Constraints"
Make sure that all the elements in the scrollview are embedded in the desired positions.
If you are not using autolayout:
Check that the Size of the view controller is set to (320, 2000), or whatever you want.
In the Simulated Metrics of the view controller, you can set the size type to Freeform.
Then in the tab to the right of Simulated Metrics, you can set the width and height to the desired values.
Please comment any concerns

Why the layout is different between storyboard and the simulator?

As below image shows, in the storyboard, I put a UIScrollView (say called A) under navigation bar and another UIScrollView (say called B) inside A. B is at the top of A.
However, in the simulator, there is big margin between B and the up bound of A (I didn't use any autolayout or write any code). Can anyone tell me the reason? Thanks.
add the below line in your - (void)viewDidLoad method
self.automaticallyAdjustsScrollViewInsets = NO;
hope it will fix your issue.
Even though you're not using Auto-layout, you have Auto-layout checked on in your Storyboard. Because you do, UIScrollViews and any Subclasses of it (UITableView, UICollectionView, etc.) all automatically adjust for the UINavigationBar height when in a UINavigationController. This is implicit and there's no way to turn it off. The only solution is to "offset the offset" or to move the UIScrollView away from the UINavigationBar.
The big margin size is navigation bar height, try add a top autolayout for your scrollView.

Swift - Can't understand the contentSize of a UIScrollView

Hi I have set in my storyboard a UIScrollView (of the same size of the view) and ctrl-dragged it in my code.
Now I have created a button programmatically using a simple algorithm of mine.
I then tried to
println(button.frame.origin.y)
which printed 1700.
Then I tried
println(button.frame.height)
which printed 142.2 (also coming from the algorithm). So the heigh I would like to reach while scrolling is 1700 + 142.2 = 1842.2
So i tried to hardcode the content size in this way
self.scrollView.contentSize = CGSize(width:self.view.bounds.size.width, height:2000)
But when I run the app I can scroll no more than the middle of the button, which is in numbers
1700 + 142.2/2 = 1771.1
Why the heck is that?
I did all this to try to understand how this UIScrollView works but I can't figure it out.
EDIT
Added a screenshot.
Inside the bubbles there is the button.frame.origin.y value. That's the max I can scroll leaving the screen untouched.
This is probably to do with scroll view insets - a mechanism where the edges of the content always appear under the navigation and toolbar.
You either need to manually account for this by reading the contentInset property of the scroll view, or using interface builder.
Scroll view Reference:
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/UIScrollView_pg/CreatingBasicScrollViews/CreatingBasicScrollViews.html

iOS: Why is my subview appearing with a big spacing inside scrollview

I have a single scrollview in my view controller and several subviews (textfields and labels). These subviews appear grouped in the middle of the screen, although I added constraints.
How can I make them appear with the standard spacing to the navigationbar?
It might be a problem with translucent nav bar.
Turn on the nav bar translucent and see if the views are correctly positioned. If they are, you have to adjust the spacing in IB.
Autolayout doesn't work the same way as everywhere else when inside a scrollview--it's a whole new ballgame (as described in apple's documentation).
If you place a UIView within the UIScrollView, and make sure you have that view the same size as the scrollview's content, you can use autolayout in this new view to place all your textfields/labels however you like.
For more info, see apple's docs on scrollviews & autolayout.
setting
self.automaticallyAdjustsScrollViewInsets = NO;
or, alternatively and corresponding in the storyboard, did fix it for iOS7. Don't know if this works for iOS 6

Resources