Based on @Brian suggestion I made this code:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat height = navigationBar.frame.size.height;
CGFloat y = scrollView.bounds.origin.y;
if (y <= 0) {
CGRect frame = navigationBar.frame;
frame.origin.y = 0;
navigationBar.frame = frame;
} else if (tableView.contentSize.height > tableView.frame.size.height) {
CGFloat diff = height - y;
CGRect frame = navigationBar.frame;
frame.origin.y = -y;
navigationBar.frame = frame;
CGFloat origin = 0;
CGFloat h = height; // height of the tableHeaderView
if (diff > 0) {
origin = diff;
h = y;
}
frame = tableView.frame;
frame.origin.y = origin;
frame.size.height = tableView.superview.frame.size.height - origin;
tableView.frame = frame;
CGRect f = CGRectMake(0, 0, tableView.frame.size.width, h);
UILabel* label = [[UILabel alloc] initWithFrame:f];
tableView.tableHeaderView = label;
[label release];
}
}
My code has a UITableView
but should work with any scrollable component. If you have other components than the navigationBar and the UIScrollView
subclass, you should change the way the height of the scrollable component is calculated. Something like this:
frame.size.height = tableView.superview.frame.size.height - origin - otherComponentsHeight;
I needed to add a dumb tableHeaderView
to have the desired behaviour. The problem was that when scrollViewDidScroll: is called the content has an offset, but the apparience in Mobile Safari is that the content is not scrolled until the navigationBar fully disappears. I tried first changing the contentOffset
.y to 0, but obviously it didn't work since all the code relies on the scrolling mechanism. So I just added a tableHeaderView
whose height is exactly the scrolled offset, so the header is never really seen, and the content appears to not scroll until the navigationBar
fully disappears.
If you don't add the dumb tableHeaderView
, then the scrollable component appears to scroll behind the navigationBar
.

With the tableHeaderView
, the scrollable component is actually scrolling (as seen in the scrollbar
), but since there is a tableHeaderView
whose height is exactly the same than the scrolled offset
, the scrollable content appears to not be scrolling until the navigationBar
fully disappears:
