Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UINavigationBar that changes transparency when scrolling

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):

Example 1

When user scrolls table view, transparency should be replaced with solid color:

Example 2

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:

Example 3

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.

like image 983
Darrarski Avatar asked Dec 22 '14 17:12

Darrarski


People also ask

How do I make my navigation bar translucent?

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 .

What is Scrolledgeappearance?

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+


2 Answers

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()
        }
    }
}
like image 142
Juan José Brown Avatar answered Oct 28 '22 03:10

Juan José Brown


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
    }
}
like image 35
Anton Lisitsyn Avatar answered Oct 28 '22 02:10

Anton Lisitsyn