I have a UIView with a transparent title bar and as the user scrolls, the background slowly fades into become white
func imageFromColor(color: UIColor, size: CGSize) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
var image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIGraphicsBeginImageContext(size)
image?.draw(in: rect)
image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
override func viewDidLoad() {
super.viewDidLoad()
// remove nav bar bottom border
navigationController?.navigationBar.shadowImage = UIImage()
// set nav bar button color
let image = imageFromColor(color: UIColor(red: 255, green: 255, blue: 255, alpha: 0.0), size: CGSize(width: 1, height: 1))
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.black.withAlphaComponent(0.0)]
As the user scrolls, I detect where they are in the scrolling and update the navigation bar appropriately
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var alpha = (scrollView.contentOffset.y / 200)
alpha = alpha > 1.0 ? 1.0 : alpha
if let listName = listName, let navBar = navigationController?.navigationBar {
let height = listName.frame.maxY - navBar.frame.maxY - 3.0
if scrollView.contentOffset.y > 0 && scrollView.contentOffset.y >= height, !titleShowing {
titleShowing = true
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn, animations: {
self.titleLabel?.alpha = 1
self.titleTopConstraint?.constant = -34.0
self.titleLabel?.layoutIfNeeded()
}, completion: nil)
} else if scrollView.contentOffset.y < height, titleShowing {
self.titleShowing = false
self.titleLabel?.alpha = 0
UIView.animate(withDuration: 0.4, delay: 0, options: .curveEaseIn, animations: {
self.titleTopConstraint?.constant = 0
self.titleLabel?.layoutIfNeeded()
}, completion: nil)
}
}
let image = imageFromColor(color: UIColor(red: 255, green: 255, blue: 255, alpha: alpha), size: CGSize(width: 1, height: 1))
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.black.withAlphaComponent(alpha)]
}
Everything works fine until I've scrolled down to where the Nav Bar turns white, then tap on an element which pushes to a view controller where again the Nav Bar should start as clear with the same setup in viewDidLoad:
let image = imageFromColor(color: UIColor(red: 255, green: 255, blue: 255, alpha: 0.0), size: CGSize(width: 1, height: 1))
navigationController?.navigationBar.setBackgroundImage(image, for: .default)
As you can see in the gif below, the Nav Bar jumps to be white rather than be clear and if I go back to the previous view controller and scroll up, the nav bar that was once clear animates from white to black, which I can't figure out. I don't have an instance of .black in the whole VC.
So to reiterate, 2 problems: 1) VC A pushes to VC B after scrolling, VC B's Nav Bar jumps to white instead of starting as clear 2) VC A pushes to VC B after scrolling, user goes back to VC A and scrolls up, Nav Bar animates from white to black instead of white to clear
Would love any help here.
Thanks!
Edit: After some investigating, it looks like since both VC A and VC B have the imageFromColor function, after the transition to B from A, the version of the function in A is being called because viewDidScroll is technically somehow called after the transition (weird). So that's why it's updating to be white rather than clear
