Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView + LargeTitle (iOS 11) - scroll to top and reveal the large title

I use the following code to scroll to top of the UICollectionView:

scrollView.scrollRectToVisible(CGRect(origin: .zero, size: CGSize(width: 1, height: 1)), animated: true)

However, on iOS 11 and 12 the scrollView only scrolls to the top, without revealing the large title of the UINavigationBar (when prefersLargeTitle has ben set to true.)

Here is how it looks like: enter image description here

The result I want to achieve:

enter image description here

like image 747
Richard Topchii Avatar asked Dec 13 '22 15:12

Richard Topchii


2 Answers

It works as it is designed, you are scrolling to position y = 0, assign your controller to be UIScrollView delegate and print out scroll offset:

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    print(scrollView.contentOffset)
}

You will see when Large title is displayed and you move your scroll view a but and it jumps back to the Large title it will not print (0.0, 0.0) but (0.0, -64.0) or (0.0, -116.0) - this is the same value as scrollView.adjustedContentInset, so if you want to scroll up and display large title you should do:

scrollView.scrollRectToVisible(CGRect(x: 0, y: -64, width: 1, height: 1), animated: true)
like image 93
Ladislav Avatar answered Dec 16 '22 03:12

Ladislav


You don't want to use any 'magic values' (as -64 in the currently accepted answer). These may change (also, -64 isn't correct anyway).

A better solution is to observe the SafeAreaInsets changes and save the biggest top inset. Then use this value in the setContentOffset method. Like this:

class CollectioViewController: UIViewController {
    var biggestTopSafeAreaInset: CGFloat = 0
            
    override func viewSafeAreaInsetsDidChange() {
        super.viewSafeAreaInsetsDidChange()
        self.biggestTopSafeAreaInset = max(ui.safeAreaInsets.top, biggestTopSafeAreaInset)
    }
    
    func scrollToTop(animated: Bool) {
        ui.scrollView.setContentOffset(CGPoint(x: 0, y: -biggestTopSafeAreaInset), animated: animated)
    }
}
like image 28
Senõr Ganso Avatar answered Dec 16 '22 04:12

Senõr Ganso