El_Chippo
El_Chippo

Reputation: 143

Nested UICollectionView does not hide NavigationBar on swipe

I have a UICollectionViewController (embedded in a NavigationViewController), which scrolls a UICollectionView horizontally via paging through some sections:

if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
        flowLayout.scrollDirection = .horizontal
        flowLayout.minimumLineSpacing = 0
}

collectionView?.backgroundColor = .white
collectionView?.register(FeedCell.self, forCellWithReuseIdentifier: cellId)
//collectionView?.contentInset = UIEdgeInsetsMake(MenuBar.height, 0, 0, 0)
//collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(MenuBar.height, 0, 0, 0)
collectionView?.isPagingEnabled = true

Each section or page contains another UICollectionView (inside the FeedCell) which scrolls vertically through some UICollectionViewCells.

Inside the UICollectionViewController, I set

navigationController?.hidesBarsOnSwipe = true

which was working as long as there was only one UICollectionView. But since the (Top)CollectionView is scrolling horizontally and is containing additional (Sub)CollectionView, that are scrolling vertically, this feature seems not to work any longer.

I would like the NavigationBar to hide when the (Sub)CollectionView is scrolling vertically. Is there any hack to achieve this?

Upvotes: 2

Views: 645

Answers (2)

Rufus Mall
Rufus Mall

Reputation: 589

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if let navigationBar = self.navigationController?.navigationBar {
        let clampedYOffset = contentOffset.y <= 0 ? 0 : -contentOffset.y
        navigationBar.transform = CGAffineTransform(translationX: 0, y: clampedYOffset)
        self.additionalSafeAreaInsets.top = clampedYOffset
    }
}

This is a solution that I came up with. Basically modify the transform of the NavigationBar to move it out the way when necessary. I also modify the additionalSafeAreaInset, as this will automatically shift all your content up to fill the space left by the navigation bar.

This function will be called as part of the UICollectionViewDelegate protocol.

This was suitable for my purposes - but if you want the navigation bar to appear when the user rapidly scrolls up (like in safari) you will have to add some additional logic.

Hope this helps!

Upvotes: 0

John Lee
John Lee

Reputation: 114

You can try the code like this (Swift 3.0):

extension ViewController: UICollectionViewDelegate {
  func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let isScrollingUp = scrollView.contentOffset.y - lastY > 0
    lastY = scrollView.contentOffset.y
    self.navigationController?.setNavigationBarHidden(isScrollingUp, animated: true)
  }

  func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate {
      // show navigation bar ?
    }
  }

  func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    // show navigationBar ?
  }
}

Upvotes: -2

Related Questions