Scrolling UICollectionView inside a container view scrolls navigation controller title

I am trying to understand if what I am seeing is expected behavior or not with the following UIKit components.

1.I have a view controller "A" embedded in a navigation controller (part of a multi-step flow). Large titles are active on this navigation controller.

  1. In this view controller "A", I have a container view that contains another view controller "B" (I want to reuse the contents of B in other flows)

  2. Inside view controller "B" I have a UICollectionView using a diffable data source.

When you load view controller "A" it appears to work fine. My collection view loads data, I see a nice list and when I scroll it...

... the expectation is it scrolls inside it's container and has no impact on the parent controller "B"

However, the navigation bar and title in "A" reflect the content offset of the collection view. Scroll a couple lines, the large title turns small and centered on top. If I turn off large title, I still see the background color of the navigation bar change as it would if you were scrolling a view directly inside controller "A" without the container view.

Am I supposed to be manually capturing the gesture recognizer in B and somehow preventing the gesture to bubble up to A? It seems like strange behavior to have to correct. Any suggestions?

Thanks!

Answered by Frameworks Engineer in 735552022

Hi! This is a case where you want to use this API: https://developer.apple.com/documentation/uikit/uiviewcontroller/3816781-setcontentscrollview

There is a simple-minded heuristic that's used to find the proper scroll view to track for the navigation bar changes. It's not unusual for it to fail for some custom view controller subhierarchies. In that case, use setContentScrollView() on view controller A to give it the scroll view you want it to track.

If there's no scrollView that the navigation bar should track, it's a little more complicated. You can't just pass nil to setContentScrollView() because that will not change the situation. However, if you override contentScrollView(for:) to return nil, that will be respected, the heuristic won't be used, and the navigation bar will remain static.

Unintended typo above.

... the expectation is it scrolls inside it's container (B) and has no impact on the parent controller (A).

Typo - ... the expectation is it scrolls inside it's container and has no impact on the parent controller "A"

Accepted Answer

Hi! This is a case where you want to use this API: https://developer.apple.com/documentation/uikit/uiviewcontroller/3816781-setcontentscrollview

There is a simple-minded heuristic that's used to find the proper scroll view to track for the navigation bar changes. It's not unusual for it to fail for some custom view controller subhierarchies. In that case, use setContentScrollView() on view controller A to give it the scroll view you want it to track.

If there's no scrollView that the navigation bar should track, it's a little more complicated. You can't just pass nil to setContentScrollView() because that will not change the situation. However, if you override contentScrollView(for:) to return nil, that will be respected, the heuristic won't be used, and the navigation bar will remain static.

Scrolling UICollectionView inside a container view scrolls navigation controller title
 
 
Q