I am trying to implement UINavigationBar
that changes its transparency when scrolling UITableView
. At the beginning, the navigation bar should have transparent background, so the content below it should be visible (there will be an image displayed, for the example I am using solid color):
When user scrolls table view, transparency should be replaced with solid color:
Table view will contain section headers, that should act like when using non-translucent navigation bar. The header views should "stick" to navigation bar once they "touch" it from the bottom:
I have no luck with trying to implement this flow in iOS app.
For the initial state, I am setting UINavigationBar
translucent
property to YES
, and both backgroundColor
and barTintColor
to clear color, which gives me what I want.
Then, when user scrolls table view, I am updating the backgroundColor
and barTintColor
to a color with given alpha component, computed basing on current scroll offset. I am using scrollViewDidScroll:
from UIScrollViewDelegate
protocol to do so. However, it changes only the background of navigation bar, leaving status bar background transparent, which is not what I want.
I can't find another way of making UINavigationBar
transparent without setting translucent
property to YES
. Unfortunately, this changes how the section headers acts when scrolling. As navigation bar is translucent, section header views hides below it when they should "stick" to the bar like on third screenshot above.
I would appreciate any help and hints how to achieve navigation bar that acts like described or similar in Objective-C or Swift.
You need to do three things to make a navigation bar transparent. Set background image to non-nil empty image ( UIImage() ). Set shadow image to non-nil empty image ( UIImage() ). Set isTranslucent to true .
The appearance settings for the navigation bar when the edge of scrollable content aligns with the edge of the navigation bar. iOS 13.0+ iPadOS 13.0+ Mac Catalyst 13.1+ tvOS 13.0+
Assuming that you have a reference to the view above the tableView and that you don't want to interact anything in it:
var overlayView:UIView!
var offsetDenominator:CGFloat!
let TARGER_COLOR = UIColor.blackColor()
override func viewDidLoad() {
super.viewDidLoad()
if let navCtrl = self.navigationController {
self.offsetDenominator = headerView.frame.size.height - navCtrl.navigationBar.frame.height
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: 0.0)
self.overlayView = UIView(frame: self.headerView.frame)
self.overlayView.backgroundColor = overlayColor
self.view.addSubview(self.overlayView)
}
...
override func scrollViewDidScroll(scrollView: UIScrollView) {
if let navCtrl = self.navigationController, let breakpoint = offsetDenominator {
let alpha = scrollView.contentOffset.y / breakpoint
if alpha >= 1.0 {
navCtrl.navigationBar.backgroundColor = self.TARGER_COLOR
} else {
let targetCIColor = CIColor(CGColor: self.TARGER_COLOR.CGColor)
let overlayColor = UIColor(red: targetCIColor.red, green: targetCIColor.green, blue: targetCIColor.blue, alpha: alpha)
self.overlayView.backgroundColor = overlayColor
navCtrl.navigationBar.backgroundColor = UIColor.clearColor()
}
}
}
My approach is:
override func viewDidLoad() {
super.viewDidLoad()
...
self.setNavbarTransculent()
}
private func setNavbarTransculent() {
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let denominator: CGFloat = 50 //your offset treshold
let alpha = min(1, scrollView.contentOffset.y / denominator)
self.setNavbar(backgroundColorAlpha: alpha)
}
private func setNavbar(backgroundColorAlpha alpha: CGFloat) {
let newColor = UIColor(red: 1, green: 1, blue: 1, alpha: alpha) //your color
self.navigationController?.navigationBar.backgroundColor = newColor
UIApplication.shared.statusView?.backgroundColor = newColor
}
extension UIApplication {
var statusView: UIView? {
return value(forKey: "statusBar") as? UIView
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With