Xcode 11.4 Navigation Bar Button Issues - ios

Since updating to Xcode 11.4 I'm running into the issue that I can't figure out how to change the color of the back arrow in the navigation bar.
Before I was able to simply use:
navigationBar.barTintColor = DisplayUtils.sweetGreenColor()
However, 11.4 has forced me to use the standardAppearance functionality to set the color of my navbar and everything. Which is no big deal, this works for setting the barTint and title colors:
navigationBar.standardAppearance.backgroundColor = DisplayUtils.sweetGreenColor()
let buttonAppearance = UIBarButtonItemAppearance()
buttonAppearance.normal.titleTextAttributes = [.foregroundColor : DisplayUtils.whiteColor()]
navigationBar.standardAppearance.buttonAppearance = buttonAppearance
navigationBar.standardAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: DisplayUtils.whiteColor(), NSAttributedString.Key.font: UIFont(name: "Roboto-Bold", size: 18) as Any]
I just don't see a property that replaced barTintColor on the UIBarButtonItemAppearance object. It lets you change the color of the text, change the image itself, but no color property.

I found a solution that works in my instance. It works because I'm creating my viewControllers in code such as:
if let stbrd = self.storyboard {
if let vc: ViewController = stbrd.instantiateViewController(withIdentifier: "VC") as? ViewController {
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil) // remove back button text
self.navigationItem.backBarButtonItem?.tintColor = DisplayUtils.sweetGreenColor()
self.navigationController?.pushViewController(vc, animated: true)
}
}
It's the line:
self.navigationItem.backBarButtonItem?.tintColor = DisplayUtils.sweetGreenColor()
That properly sets the color of the back arrow on the newly presented view controller.
I still don't see how to simply set that color on the view controller itself like before this change. So, if anyone can offer up that knowledge it would be great.

On the storyboard, for your Navigation Controller change the "Bar Tint" to its "Default" value, then on your code you can change it as you normally would.
By programmatically simply first change navigation bar color to default then you can update what you are already doing.
if #available(iOS 13.0, *) {
self.navigationController?.navigationBar.standardAppearance.configureWithDefaultBackground()
}

Related

Transition to UIDocumentInteractionController takes over navigation bar title color

Just doing a simple transition a UIDocumentInteractionController to display a PDF. Its title is black, which is desired, but I want it to go back to the app color (white) when it goes back. Trying to force a change in viewWillAppear does nothing (though I do see viewWillAppear is being called). I also tried changing the color in documentInteractionControllerDidEndPreview but again nothing happens. The color stays black.
Using the following to change the color:
let textAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
self.navigationController?.navigationBar.largeTitleTextAttributes = textAttributes
Giving the UIDocumentInteractionController the navigation controller:
open func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
guard let vc = self.navigationController else {
fatalError("No navigation controller")
}
return vc
}
How can i have a black title when presenting the document and white (or whatever color I desire) when i go back? This should be something simple but ive been going in circles.
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
navBarAppearance.backgroundColor = .clear
self.navigationController?.navigationBar.standardAppearance = navBarAppearance
Calling this in viewDidLoad fixed the problem

Use `navigationItem.backButtonDisplayMode = .minimal` with a custom back button image

For an iOS 14+ app I'd like to use navigationItem.backButtonDisplayMode = .minimal to hide the back button title, while still having the title available in the back button's long-press menu. Which works.. however I also want to change the back button image, to replace the default chevron.
But no matter what I try, I can't seem to find a solution that shows a custom back button image without a title, while also not showing a blank space in the back button's long-press menu, and not breaking the slide-to-go-back-gesture.
Anyone tried something similar, and succeeded?
So in the first view controller I show a title:
And then in the pushed view controller I want to show a custom back button image WITHOUT the "one" title (as seen below), and still have the long-press menu say "one" instead of a blank space.
This mostly gets me there actually, except that it breaks the gesture to slide to go back:
override func viewDidLoad() {
super.viewDidLoad()
let backImage = UIImage(named: "backImage")?.withRenderingMode(.alwaysOriginal)
navigationController?.navigationBar.backIndicatorImage = backImage
navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
navigationItem.backButtonDisplayMode = .minimal
}
Update: actually it only seems to break on the simulator, it's all fine on an actual device. I now have a minimal project setup where it all works, now to find out why it doesn't work in my actual big project!
Okay, I finally figured out all the problems I was having.
Basically, this code works just fine:
override func viewDidLoad() {
super.viewDidLoad()
let backImage = UIImage(named: "backImage")?.withRenderingMode(.alwaysOriginal)
navigationController?.navigationBar.backIndicatorImage = backImage
navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
navigationItem.backButtonDisplayMode = .minimal
}
But I was having problems with the swipe back gesture not working anymore. Turns out, that's a simulator bug, works fine on device. Then there was the problems that the custom back button image didn't actually show up in my view, because of this:
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .pageBackground
appearance.titleTextAttributes = [.foregroundColor: UIColor.abbey]
appearance.shadowColor = .clear
navigationBar.scrollEdgeAppearance = appearance
navigationBar.standardAppearance = appearance
navigationBar.compactAppearance = appearance
As soon as you set a custom appearance, that completely wipes away the custom back button image. Simple fix, just set these things directly on the navigationBar without involving the appearance.
And now it all works!
To set the image, you can use:
navigationController?.navigationBar.backIndicatorImage = yourBackImage
navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
Let's say you have navigation from AVC to BVC.
If you want to disable the long press menu, you can follow this answer.
If you want the long press menu to work with the correct titles, you need to set navigationItem.title for your AVC to the right value, and navigationItem.backBarButtonItem should be nil(it's the default value) for BVC.
If you don't want to display the title in your AVC, you can hide it with titleView:
navigationItem.title = "title for long press navigation menu"
navigationItem.titleView = UIView()

UIDocumentPickerViewController navigation bar buttons color

My app is using red navigation (2) bar with white buttons and texts. When I use system contact picker (3) the status bar is red. When I use documents picker (1) UIDocumentPickerViewController then navigation bar is white. How I can change color of navigation bar or text?
When I use code bellow, it works but it change my navigation bar too.
UINavigationBar.appearance().tintColor = .red
thanks for help
code:
func open() {
UINavigationBar.appearance().barTintColor = .green
let documentsController = UIDocumentPickerViewController(documentTypes: makeDocumentTypesList(), in: .import)
documentsController.delegate = self
viewControllerProvider.getViewController().present(documentsController, animated: true, completion: nil)
}
You can just reset the appearance for UIDocumentPickerViewController only by putting this code somewhere in your application:didFinishLaunchingWithOptions: function and the bar buttons will return to their original blue or you can set any other color of your choice. The bar color, on the other hand is not customizable.
if #available(iOS 11.0, *) {
UINavigationBar.appearance(whenContainedInInstancesOf: [UIDocumentBrowserViewController.self]).tintColor = nil
}
Use setTitleTextAttributes
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.white], for: .normal)
see my answer here
This is the only solution I found:
UINavigationBar.appearance().tintColor = ... some color
_viewController?.present(documentPicker, animated: true)
To my knowledge it is not possible to set the bar color only the tint color (text color). To keep the tint color for the rest of your project I reset it in the viewWillAppear of the underlying view controller.
as you ask "change color of navigation bar or text?"
i haven't a solution for change navigation bar it always return nil
self.present(documentPicker, animated: true,completion: {
if documentPicker.navigationController?.navigationBar != nil{
documentPicker.navigationController?.navigationBar.barTintColor = .red
}
})
but if you agree to change only text
this works for me
self.present(documentPicker, animated: true,completion: {
documentPicker.view.tintColor = .red
})
i understand that it couldn't be the optimal but none of solutions i try work for me

Navigation bar button not showing with tinted color iOS

I am having view controllers
And I am showing like this
Let assume 1,2,3 are the view controllers.
I navigate like this
1->2->3
When I come back
3->2->1
then from 1 the navigation bar button item cancel of UIImagePicker doesn't show. If I don't go with this sequence (1->2->3
) It shows perfectly.
Please let me know what could be the issue.
I am using opaque navigation bar.
And the navigation bar tint and bar tint color I am updating like this in the appdelegate class
func setNavigationAppearance(tintColor : UIColor, barTintColor : UIColor?) {
let navigationBarAppearace = appDelegateObj.navigationController!.navigationBar
navigationBarAppearace.tintColor = tintColor
navigationBarAppearace.barTintColor = tintColor
navigationBarAppearace.translucent = false
//navigationBarAppearace.
//Settign the Custome Font and TextColor
if let font = UIFont(name: FontCustom.Regular, size: 17) {
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName: font ,NSForegroundColorAttributeName : tintColor]
}
}
And adding the background image to the navigation bar like this
if let myImage = UIImage(named: AppImagesName.PatternRed) {
UINavigationBar.appearance().setBackgroundImage(myImage, forBarMetrics: .Default)
}

Swift 3: How to set up UINavigationBar setBackgroundImage in AppDelegate

I recently migrated from Swift 2 to Swift 3 and I'm stuck on one part. In my AppDelegate, I'd set up the default settings for the UINavigationBar as coded below. The challenge I'm having is that the setBackgroundImage is no longer recognized in Swift 3 and I can't find an alternative.
Has anyone had the same issue happen and been able to resolve it?
let turquoiseBackgroundImage:UIImage = UIImage(named: "navigationBarTurqoise")!
**// TODO Below is not working with Swift 3
UINavigationBar.appearance().setBackgroundImage(turquoiseBackgroundImage, forBarPosition: .Default)**
// Set up Back button to be white in Navigation bar
UINavigationBar.appearance().barStyle = UIBarStyle.default
UINavigationBar.appearance().tintColor = UIColor.white
// Font Name and Size of Title in Navigation Bar
if let font = UIFont(name: "TitilliumWeb-Light", size: 20) {
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : font, NSForegroundColorAttributeName : UIColor.white]
}
// Remove hairline between navigation bar and anything below such as search bar
UINavigationBar.appearance().shadowImage = UIImage()
// Set up status bar (battery, time, etc.) to white
UIApplication.shared.statusBarStyle = .lightContent
UINavigationBar.appearance().setBackgroundImage(turquoiseBackgroundImage, forBarPosition: .Default)
rewrite code like this
UINavigationBar.appearance().setBackgroundImage(turquoiseBackgroundImage, for: .default)

Resources