I have an odd situation where I cannot for the life of me get an app to start with the UINavigationBar set to transparent black. The app consists of a UINavigationController with a UIPageViewController as root. These are loaded from a storyboard when the app launches.
The app runs and the UINavigationBar shows up as opaque. As soon as I start dragging the UIPageViewController it triggers some sort of redraw and the UINavigationBar becomes transparent as desired.
I tried a few different ways of setting the UINavigationBar to transparent black, and none of them produced behavior any different than described:
I set these keys in Info.plist:
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleBlack</string>
<key>Translucent</key>
<true/>
</dict>
</dict>
I set the UINavigationBar appearance in the AppDelegate in didFinishLaunchingWithOptions:
UINavigationBar.appearance().tintColor = UIColor.black
UINavigationBar.appearance().isTranslucent = true
I subclassed UINavigationController and set NavigationBar properties in viewDidLoad():
navigationBar.barStyle = .black
navigationBar.isTranslucent = true
navigationBar.setNeedsDisplay()
I set the NavigationBar properties in viewDidLoad() of the UIPageViewController (the navigation controller's root view controller):
navigationController!.navigationBar.barStyle = .black
navigationController!.navigationBar.isTranslucent = true
navigationController!.navigationBar.setNeedsDisplay()
I also tried toggling the navigation bar on / off to trigger a refresh
navigationController!.isNavigationBarHidden = true
navigationController!.isNavigationBarHidden = false
For the sake of completion, I set the navigation bar properties in viewDidLoad() of the child view controller of the UIPageViewController.
In every single case I get the same behavior: opaque bar until I touch the screen and start a drag, at which point it switches to transparent.
What's odd is that setting other attributes of the navigation bar, such as titleTextAttributes, leftButtonItem, and rightButtonItem works just fine and the changes are reflected immediately.
I had a similar requirement with Swift3 an achieved it in this way:
In your view controller which contains PageViewController add the following code in viewDidLoad()
func makeNavigationTranslucent() -> Void {
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.view.backgroundColor = UIColor.clear
self.navigationController?.navigationBar.backgroundColor = UIColor.init(colorLiteralRed: 0.5, green: 0.5, blue: 0.5, alpha: 0.9)
}
Note : Change navigationBar.backgroundColor to the one which you want.
In your storyboard select your controller and under attribute inspector with simulated metrics heading set top bar to Navigation Translucent Bar. Refer below image :
This is kind of a hacky solution, but I managed to get it working by hiding the default navigation bar and adding a new one over it. In the page view controller viewDidLoad() function:
navigationController!.isNavigationBarHidden = true
let newNavBar = UINavigationBar()
newNavBar.barStyle = .black
newNavBar.isTranslucent = true
newNavBar.titleTextAttributes = [NSFontAttributeName: UIFont.mainFontThin(24),
NSForegroundColorAttributeName: UIColor.white]
// etc...
navigationController!.view.addSubview(newNavBar)
newNavBar.frame = CGRect(
x:0, y:0,
width:navigationController!.view.bounds.width,
height:navigationController!.navigationBar.frame.height + UIApplication.shared.statusBarFrame.height
)
newNavBar.pushItem(navigationItem, animated: false)
This shows the translucent navigation bar like we want, but there's still a small problem where the app status bar is black under the translucent nav bar. As before, once you drag a finger the status bar updates to transparent. I'm not sure how to fix this, adding a call to setNeedsStatusBarUpdate() didn't help. So this is a partial fix.
Related
I am really struggling figuring out why there's a part on top of the navigation bar that has a different color than the navigation bar.
I have set the navigation like this:
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.backgroundColor = .primaryBlack
navigationController?.setNavigationBarHidden(false, animated: true)
And for some reason only one part is with that color but not everything. In some other parts that part is completely transparent making it look really odd.
I encountered this issue when ever my navigation bar is using large titles and push a view controller onto the navigation stack of the navigation controller, this gap seems to be at the top:
There seems to be some gap created for some reason and the large title navigation bar starts under the status bar.
The reason I understand as per the documentation is that the base view goes under the UINavigationBar and when this view is scrolled, the UINavigationBar needs to transform.
When a navigation controller contains a navigation bar and a scroll
view, part of the scroll view’s content appears underneath the
navigation bar. If the edge of the scrolled content reaches that bar,
UIKit applies the appearance settings in this property.
Simplest thing I do is to make the underlying view the same color as the navigation bar background in the view controller and keep the result of your code the same:
// Same as your code, only changed background to blue
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.backgroundColor = .blue
navigationController?.setNavigationBarHidden(false, animated: true)
// What I added
view.backgroundColor = .blue
This gives me:
Update using UINavigationBarAppearance
Can you try updating using UINavigationBarAppearance
// From your code, not sure of it's purpose
navigationController?.setNavigationBarHidden(false, animated: true)
let appearance = UINavigationBarAppearance()
// Color of the nav bar background
appearance.backgroundColor = .black // primary black for you
// Color for the titles
appearance.largeTitleTextAttributes
= [NSAttributedString.Key.foregroundColor : UIColor.white]
appearance.titleTextAttributes
= [NSAttributedString.Key.foregroundColor : UIColor.white]
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
// Color for the back button
navigationController?.navigationBar.tintColor = .white
Result:
I have tested this on a sample project with 2 view controllers defined in the storyboard using Xcode 11 (iOS 13). The "presenting" view controller is embedded in a navigation controller and has the navigation bar colors set in the viewWillAppear.
The "search" view controller adds a UISearchController in the viewDidLoad and is pushed by the presenting view controller (NOT modal).
With just this setup when the search view controller is displayed the navigation bar has the blue background and red tint color as expected. However when scrolling down and the search bar is displayed the background color of the navigation bar is lost (or changed to what appears to be the default iOS grey / translucent). However if you scroll back up (hide the search bar) or focus on the search bar text field the navigation bar color returns!
Also if you focus on the search bar text field and then cancel (by tapping the Cancel button) the tint color of the navigation bar reverts from red to the default iOS blue as can be noticed by the back bar item.
Any suggestions on resolving this issue?
I have set the navigation bar colors in the viewWillAppear of the search controller too which didn't change this behaviour.
I set isTranslucent to true for the navigation bar in the search controller which seemed to prevent the reverting of the background color but it did not change the reverting of the tint color on cancel.
Presenting View Controller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.barTintColor = .blue
navigationController?.navigationBar.tintColor = .red
}
Search View Controller
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Search VC"
searchController.dimsBackgroundDuringPresentation = false
searchController.obscuresBackgroundDuringPresentation = false
navigationItem.searchController = searchController
definesPresentationContext = true
}
EDIT
Setting the scrollEdgeAppearance, backButtonAppearance and buttonAppearance as suggested works a treat except for system bar buttons that default to the iOS blue. This can be resolved by setting the UINavigationBar.tintColor but neither that resolves the back button chevron color defaulting on cancel of the search.
if #available(iOS 13.0, *) {
let buttonAppearance = UIBarButtonItemAppearance()
buttonAppearance.configureWithDefault(for: .plain)
buttonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.red]
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.configureWithOpaqueBackground()
navigationBarAppearance.backgroundColor = .blue
navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.red]
navigationBarAppearance.backButtonAppearance = buttonAppearance
navigationBarAppearance.buttonAppearance = buttonAppearance
navigationBarAppearance.doneButtonAppearance = buttonAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navigationBarAppearance
navigationController?.navigationBar.compactAppearance = navigationBarAppearance
navigationController?.navigationBar.standardAppearance = navigationBarAppearance
} else {
navigationController?.navigationBar.barTintColor = .blue
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.red]
navigationController?.navigationBar.tintColor = .red
}
However when scrolling down and the search bar is displayed the background color of the navigation bar is lost
All of that is normal. New in iOS 13, the expanded nav bar (displaying search bar, large title, etc.) has different appearance from the normal nav bar. Your settings applied only to the normal nav bar because you didn't make them the iOS 13 way. If you want the expanded nav bar to look like the normal nav bar, you have to set its appearance separately and explicitly.
To do so, you need to set the navigation bar's scrollEdgeAppearance. Investigate classes UIBarAppearance, UINavigationBarAppearance, and UIBarButtonItemAppearance (you will need to set the backButtonAppearance explicitly).
I have the nav bar transparent with only the bar button being displayed in my app. In my storyboard I have no title so that the nav bar looks like nothing is there, but when I run the simulator, the text that I deleted is in the nav bar.
This is what i've found to solve problem:
What the nav bar should look like without the transparency
What the nav bar looks like in the simulator
My code for making the bar transparent:
//Makes navigation bar translucent
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
In your code, inside view will appear method
use this code
self.title = "" // or whatever text you have
In your app delegate, did finish launching with option method:
UINavigationBar.appearance().barTintColor = .white
UINavigationBar.appearance().isTranslucent = false
UINavigationBar.appearance().titleTextAttributes =
[NSForegroundColorAttributeName: UIColor.black] // shouldn't be needed, but if you want something
UINavigationBar.appearance().tintColor = .blue
From your storybord remove any changes done by you. It can be done from code, also since it needs to be consistent in the app. Try to handle status bar and navigation bar from code itself.
I want to make my tabbar half transparent by setting the translucent value to true. However it is not doing the trick. I have a TabBarVC assigned to the tab bar with the following code. The tab bar remains solid
class TabBarVC: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// color of background -> This works
self.tabBar.barTintColor = UIColor.purpleColor()
// color when selected -> This works
self.tabBar.tintColor = UIColor.redColor()
// This does not work
self.tabBar.translucent = true
}
I also tried to do something like
UIColor(red: 246.0/255, green: 246.0/255, blue: 246.0/255, alpha: 0.5)
But it does not seem to work. I did a bit of search on Google but everyones issue seems to differ from mine. Could anyone help me out here?
Thanks,
What you're doing is most likely working to adjust the transparency of the tab bar. However, you need to set the corresponding view controllers to be "Under Bottom Bar" in the IB.
I am trying to change the color of my navigation bar in a view which contains a UISearchController. I have previously set the color of my navigation bars for the whole app in my appDelegate, but i want this views nav bar to have a different color. The issue is that i dont know which function to place the code such that it will override the appDelegate code. For example, viewDidLoad and viewWilAppear do not change the color when the view first loads, only after i enter and cancel the searchController. Which function should i place the following?
UINavigationBar.appearance().backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
There are two ways to do this. You can either modify the appearance proxy that you have set up in the AppDelegate for the whole app, or you can modify the individual navigationbar for the particular screen.
When you dismiss the view - you need to reset the barTintColor in the viewWillDisappear.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Set to new colour for whole app
UINavigationBar.appearance().barTintColor = UIColor.blueColor()
// Or, Set to new colour for just this navigation bar
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
//Revert to old colour, whole app
UINavigationBar.appearance().barTintColor = UIColor.redColor()
//Revert to old colour, just this navigation bar
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
}
Instead of changing the navigation bars color directly, you should change the navigation controller's bar color in viewWillAppear and change it back when you dismiss the view.