How to make a nav bar transparent before scrolling (iOS 14)

Viewed 890

I'd like to implement a nav style like what is found in the "Add Reminder" view controller from Apple's Reminders (iOS 14). I've tried hooking into the scrollview delegate methods but I'm not sure how to change the alpha of the default nav bar background/shadow image.

enter image description here

I've tried changing the nav bar style on scroll and, while that works, it doesn't fade in/out like in the example. That makes me think the answer lies manipulating the alpha value. Thanks in advance!

1 Answers

I've found a (hacky) solution that works in iOS 14 (untested in other versions). It makes an assumption about the private view structure of UINavigationBar, so there's no guarantee that it will work in future iOS versions, but it's unlikely to crash - the worst that should happen is that the bar will fail to hide, or only partially hide.

Assuming that you are placing the code inside a UIViewController subclass that it acting as the delegate for a UITableView, UICollectionView or UIScrollView, the following should work:

override func viewDidLoad() {
    super.viewDidLoad()
    // this hides the bar initially
    self.navigationController?.navigationBar.subviews.first?.alpha = 0
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard let navigationController = self.navigationController else { return }
    let navBarHeight = navigationController.navigationBar.frame.height
    let threshold: CGFloat = 20 // distance from bar where fade-in begins
    let alpha = (scrollView.contentOffset.y + navBarHeight + threshold) / threshold
    navigationController.navigationBar.subviews.first?.alpha = alpha
}

The magic threshold value is a little hard to explain, but it's basically the distance from the bar at which the fade in will start. A value of 20 means the bar starts to fade in when the scrollView content is 20 points away. A value of 0 would mean the bar snaps straight from fully transparent to fully opaque the moment the scrollView content touches it.

Related