20

I have 2 ViewControllers embedded in a Navigation Controller shown in the picture below.

enter image description here

Every time I scroll through my table item, the navigation background color keeps changing along with the status bar background color.

How do I set the backgroundColor of my navigation bar and status bar programmatically?

enter image description here enter image description here

Code:

import UIKit

class TestViewController: UIViewController, UIGestureRecognizerDelegate {

    @IBOutlet weak var tableView: UITableView!
    
    let faqList : [FAQ] = [
        FAQ(title: "Test 1", content: "Answer 1"),
        FAQ(title: "Test 2", content: "Answer 2"),
        FAQ(title: "Test 3", content: "Answer 3"),
        FAQ(title: "Test 4", content: "Answer 4"),
        FAQ(title: "Test 5", content: "Answer 5"),
        FAQ(title: "Test 6", content: "Answer 6"),
        FAQ(title: "Test 7", content: "Answer 7"),
        FAQ(title: "Test 8", content: "Answer 8"),
        FAQ(title: "Test 9", content: "Answer 9"),
        FAQ(title: "Test 10", content: "Answer 10"),
        FAQ(title: "Test 11", content: "Answer 11"),
        FAQ(title: "Test 12", content: "Answer 12"),
        FAQ(title: "Test 13", content: "Answer 13"),
        FAQ(title: "Test 14", content: "Answer 14"),
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self

        tableView.backgroundColor = UIColor(named: "BackgroundColor")
        tableView.register(UINib(nibName: "ButtonTableViewCell", bundle: nil), forCellReuseIdentifier: "ButtonCell")
        self.navigationController?.navigationBar.backgroundColor = .blue
    }
}

extension TestViewController: UITableViewDelegate {
    
}

extension TestViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return faqList.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCell", for: indexPath) as! ButtonTableViewCell
        let buttonCell = faqList[indexPath.row]
        cell.titleLabel.text = buttonCell.title
        cell.trailingIconBackground.isHidden = true

        cell.buttonView.backgroundColor = .brown
        cell.buttonView.layer.cornerRadius = 10
        cell.buttonView.layer.masksToBounds = true

        cell.selectionStyle = UITableViewCell.SelectionStyle.none
        
        return cell
    }
}
Punreach Rany
  • 2,560
  • 7
  • 23
  • 56

12 Answers12

27

Paste this to AppDelegate and if you have tab bar also then paste tabbarappearance also it will work.

if #available(iOS 15, *) {
    let navigationBarAppearance = UINavigationBarAppearance()
    navigationBarAppearance.configureWithOpaqueBackground()
    navigationBarAppearance.titleTextAttributes = [
        NSAttributedString.Key.foregroundColor : UIColor.white
    ]
    navigationBarAppearance.backgroundColor = UIColor.blue
    UINavigationBar.appearance().standardAppearance = navigationBarAppearance
    UINavigationBar.appearance().compactAppearance = navigationBarAppearance
    UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
    
    let tabBarApperance = UITabBarAppearance()
    tabBarApperance.configureWithOpaqueBackground()
    tabBarApperance.backgroundColor = UIColor.blue
    UITabBar.appearance().scrollEdgeAppearance = tabBarApperance
    UITabBar.appearance().standardAppearance = tabBarApperance
}
Cheolhyun
  • 169
  • 1
  • 7
Bikesh Thakur
  • 846
  • 7
  • 22
  • Thanks for sharing including titleTextAttribute. In latest Xcode, we don't have to set compactAppearence separately if it's same as standard appearance. – Sujananth Mar 22 '22 at 09:54
  • Thanks. Works perfectly. Instead of setting UIColor.blue, I set it to "`.clear`", which worked out well. (BTW: side note - you don't need to add "`UIColor`" prefix to a color enum when assigning it something that is already typed UIColor (like backgroundColor). Similarly, no need to add a redundant type prefix to an enum value when passing it as a function argument if the argument in the function declaration ("formal parameter") defines the type (such as UIColor) already ... in other words, in function calls and assignments, enum type during assignment is *implied* by type of the receiver). – clearlight Sep 21 '22 at 17:08
9

Just use below code. I fixed same issue:

// Below code will fix Navigation bar issue fixed for iOS 15.0
        if #available(iOS 15, *) {
            let appearance = UINavigationBarAppearance()
            appearance.configureWithOpaqueBackground()
            self.navigationController?.navigationBar.isTranslucent = true  // pass "true" for fixing iOS 15.0 black bg issue
            self.navigationController?.navigationBar.tintColor = UIColor.white // We need to set tintcolor for iOS 15.0
            appearance.shadowColor = .clear    //removing navigationbar 1 px bottom border.
            UINavigationBar.appearance().standardAppearance = appearance
            UINavigationBar.appearance().scrollEdgeAppearance = appearance
        }
Kudos
  • 1,224
  • 9
  • 21
8

For your navigation bar, you will find "Appearance" check both "Standard" and "Scroll edge" Then you will find multiple "Background" attributes in the inspector, change both Backgroungs one under "Standard appearance" section and the other under "Scroll edge appearance" section then it should work properly

  • 2
    I'll give you some love here...this worked for me...it amazes me all the options and levers you have to get "just" right to achieve your desired effect. For example, what's the difference in opaque and translucent? What if you only have 1 picked? both picked? Neither picked? Such a puzzle...thanks again. – iTrout Mar 10 '22 at 19:42
  • 3
    This is 100% this right answer. Was trying to figure this out for days. Fixed it for me in 15.4 (xcode 13.3) – meltonCG Mar 23 '22 at 16:20
  • 2
    Hey thanks guys it's cool to see my comment is actually helping haha – أبو فهد Morphine pill Mar 27 '22 at 08:47
5

Just simply add empty image to the navigationBar background like below:

 navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
 navigationController?.navigationBar.shadowImage = UIImage()
3

Go to the main navigation bar from the storyboard, then show "the attributes inspector", from the appearance options list, tick "standard" and untick others (compact, scroll edge..)

Then a new set of options will appear group named "Standard Appearance", edit the "background" option to the desired color.

enter image description here

Omar N Shamali
  • 503
  • 5
  • 11
  • 1
    Perfect, I used Xcode 14.3, with this config interface, every stage could be edited and preview from storyboard. It's awesome. – Dennies Chang May 17 '23 at 03:18
2

In IOS 15, UINavigationBar uses scrollEdgeAppearance which has a transparent backgroundcolor by default and its triggered when you scroll to view . you need to set a spesific apperance for this like

   let appearance = UINavigationBarAppearance()
   appearance.backgroundColor = .blue
  navigationController?.navigationBar.scrollEdgeAppearance = appearance
Omer Tekbiyik
  • 4,255
  • 1
  • 15
  • 27
  • 1
    But if I do that, I can't customize my back button (Can't change the icon or text). Now we can replace it with a `UIBarButtonItem`. With that, we can go back but we can't swipe back unless we implement `interactivePopGestureRecognizer`, which might have to be done in every pages. – Punreach Rany Nov 11 '21 at 08:51
  • You can customize your back button or text but yes you need to add this delegete to current viewcontroller if you want to enable pop view controller with swipe action – Omer Tekbiyik Nov 11 '21 at 08:57
2

Just copy and paste this into your AppDelegate.swift file.

UINavigationBar.appearance().barTintColor = .white
UITabBar.appearance().barTintColor = .white

Also, you can change the colors to your custom one. It will work perfectly.

1

Try change translucent property of navigation bar.

self.navigationController?.navigationBar.isTranslucent = false
bdeviOS
  • 449
  • 1
  • 6
1

On a project with the same problem, I applied a solution also for the TabBar. In the case of using storyboards.

In each inspector uncheck the boxes for Appearances.

Set the custom color for Bar Tint and possibly Background.

1

enter image description here

Check all the appearances and change the background color of all the Appearances to your preferred color.

Simran Singh
  • 445
  • 6
  • 8
0

Try this code in your base view controller.

This is a transparent navigation bar.

    ///Fix navigation bar color change issue in ios 15
    if #available(iOS 15.0, *) {
        let navigationBarAppearance = UINavigationBarAppearance()
        navigationBarAppearance.configureWithTransparentBackground()
        UINavigationBar.appearance().standardAppearance = navigationBarAppearance
        UINavigationBar.appearance().compactAppearance = navigationBarAppearance
        UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
    }
0

Facing the same issue and did not get resolved with Appearance changes. Finally this one works for me :

navigationController.view.backgroundColor = {your color}

Arjun hastir
  • 476
  • 2
  • 4
  • 13