hide and show a ui nav bar button - ios

I am having a situation in which I have to hide the button on the right side of nav bar. Button name is btnRefresh, and I can hide it successfully by this way
self.nvbar.topItem?.rightBarButtonItem = nil
but when I use this for showing it again, it didn't get displayed again
self.nvbar.topItem?.rightBarButtonItem = btnRefresh
Any help???

You need to change the tint color to clear and disable the button as the following :
let barButtonItem = UIBarButtonItem()
barButtonItem.tintColor = .clear
barButtonItem.isEnabled = false
And to display it again change the color and enable it again :
barButtonItem.tintColor = .black
barButtonItem.isEnabled = true

Related

Cancel button text color on Mail Compose View Controller

I am using iOS 14 device and whenever I open Mail View Composer, the 'Cancel' button on top left corner always shows up in white. I was able to set the color of send button, but not able to change the color for 'Cancel' button.
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(toRecipientEmailIds)
mailComposerVC.setSubject(subject)
mailComposerVC.setMessageBody(messageBody, isHTML: false)
if let topVC = UIApplication.shared.topMostViewController() {
mailComposerVC.navigationBar.tintColor = UIColor(rgb: 0x057AFF)
//mailComposerVC.navigationBar.isTranslucent = false
//mailComposerVC.navigationBar.isOpaque = false
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).tintColor = UIColor.white
topVC.present(mailComposerVC, animated: true)
}
How do I change text color for 'Cancel' button?
Thanks!
Remove the below as it probably is what is causing your cancel button to be white
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).tintColor = UIColor.white
You only need this
// set any color you want
mailComposerVC.navigationBar.tintColor = .green
Maybe your AppDelegate.swift has set the value for all the NavigateBar
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .normal)
Just remove above line, you will be able to set your mail cancel button color.
Please refer to this post:
Cancel and send button missing on MFMailComposeViewController iOS

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

Why is UISearchController changing the navigation bar colors?

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

Supplymentary header view not taking to status bar collection view

I make this screen with collection view with using supplementary HeaderView. I want to make this HeaderView to the status bar. I make clear color to status bar but it is not working. Please help me with it.
I think you need to make the next, delete this view and put this image in the back of the navigation bar, the next is putting navigation bar transparent and the tint color in white like this :
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.view.backgroundColor = .clear
self.navigationController?.navigationBar.tintColor = UIColor.white
You could try to get the contents of the collection view started earlier.
collectionView.contentInset.top = -14
So, first of all in your info.plst tap "+" button and this line.
Than in your UIViewController add this method.
override var prefersStatusBarHidden: Bool {
return true
}
Status bar will be hidden only in this viewController.

Nav bar displays text in simulator but not storyboard

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.

Resources