2

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!

  • You might be looking for [`scrollEdgeAppearance`](https://developer.apple.com/documentation/uikit/uinavigationbar/3198027-scrolledgeappearance) – aheze Dec 18 '20 at 19:29
  • I tried but I’m pretty sure scrollEdgeAppearance only works with a nav bar with .prefersLargeTitles = true. – peyton.shetler Dec 18 '20 at 19:30
  • @aheze That’s just what I and a few others have found, but I’m happy to be wrong if you can get it working haha – peyton.shetler Dec 18 '20 at 19:31
  • "not sure how to change the alpha of the default nav bar background/shadow image" Probably straightforward manipulation of the UINavigationBarAppearance properties. – matt Dec 18 '20 at 20:01
  • @matt You're probably right. I've tried a lot of them at this point just not sure which ones. Probably gonna have to just scroll through them all haha. – peyton.shetler Dec 18 '20 at 20:08
  • Well this is the standard appearance, and there are transparent defaults and opaque defaults and you can probably just switch between them. – matt Dec 18 '20 at 20:56
  • @matt Totally. I tried doing that and, while it works, it doesn't exactly match what's shown above in the gif. Changing the defaults on scroll creates a sudden change. If you look in the gif, or in the Reminders app, the default nav FADES in/out based on the scroll position. It's the scroll behavior that made me think it might have something to do with the alpha component. – peyton.shetler Dec 18 '20 at 20:58
  • I cannot help suspecting that here, as evidently in Safari, Apple is taking advantage of API to which there is no public access. – matt Dec 18 '20 at 22:43
  • @matt Ah. So, just so I’m tracking with what you’re saying, You’re thinking it’s probably an API that we don’t have access to? – peyton.shetler Dec 18 '20 at 22:44
  • Yes, the way things collapse and fade as you scroll looks like something we can’t imitate. – matt Dec 18 '20 at 22:49
  • I figured it out! I’ll post my answer later – peyton.shetler Dec 22 '20 at 20:24
  • @peyton.shetler what was the solution? – Nick Lockwood Jan 18 '21 at 00:05

1 Answers1

4

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.

Nick Lockwood
  • 40,865
  • 11
  • 112
  • 103
  • Here’s a link to my medium article explaining. If I’m reading your solution correctly, then I believe we’ve come to the same conclusion! I utilized the scroll view delegate and a view inserted into the nav bars sunburns. It’s a bummer we have to hack it together though, I wish Apple would make this available to the rest of us. – peyton.shetler Jan 18 '21 at 01:31
  • 1
    The main difference AFAICT is that I'm not adding a new view to the navbar, but just setting the alpha directly on the background view that's already in there. – Nick Lockwood Jan 18 '21 at 08:37