I need to display my app's icon in the navigation bar. To do this, I have added it as a right bar button item. I don't want it to be clickable, I just need the icon there, so I set it to disabled. The problem with this is the icon appears grey, instead of green. Is there a way to disable this button but also keep it's original color?
8 Answers
Try this:
let barButtonItem = UIBarButtonItem(title: "Click", style: .Done, target: self, action: #selector(didClick(_:)))
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.blueColor()], forState: .Normal)
barButtonItem.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.blueColor()], forState: .Disabled)
barButtonItem.enabled = false
navigationItem.setRightBarButtonItem(barButtonItem, animated: false)
try
[button setBackgroundImage:yourIconImage forState:UIControlStateDisabled];
[button setEnabled:NO]

- 317
- 2
- 11
The accepted answer does not work for me (I think it's because I'm using an image, not text).
You can initialize a UIBarButtonItem using a custom view, so in order to solve the issue I subclassed UIBarButtonItem so that it takes a UIButton as an initializer argument.
Here is the code.
class TintableBarButtonItem: UIBarButtonItem {
private(set) var button: UIButton!
override var tintColor: UIColor? {
get { return button.tintColor }
set { button.tintColor = newValue }
}
convenience init(button: UIButton) {
self.init(customView: button)
self.button = button
button.imageView?.contentMode = .scaleAspectFit
button.frame = CGRect(x: 0, y: 0, width: 34, height: 30)
}
}
And I used it like this in my ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton()
let image = #imageLiteral(resourceName: "MyIcon").withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
let barButton = TintableBarButtonItem(button: button)
navigationItem.rightBarButtonItem = barButton
}
I got the frame dimensions using the method here: https://stackoverflow.com/a/45374012/6167296
You will also have to set the target-actions on the button itself. You can see a similar answer here: https://stackoverflow.com/a/2796488/6167296

- 2,234
- 1
- 19
- 35
myBarButtonItem.setBackgroundImage(myIconImage, forState: .Normal, barMetrics: .Default)
myBarButtonItem.setBackgroundImage(myIconImage, forState: .Disabled, barMetrics: .Default)
myBarButtonItem.enabled = false

- 8,449
- 6
- 44
- 48
To set the color for disabled state across the entire app, you can do the following once in your AppDelegate
's application:didFinishLaunchingWithOptions:
:
let attributes: [String: Any] = [
NSForegroundColorAttributeName: UIColor.red.withAlphaComponent(0.5)
]
UIBarButtonItem.barAppearanceWhenContained(in: UINavigationBar.self)
.setTitleTextAttributes(attributes, for: UIControlState.disabled)

- 9,832
- 10
- 51
- 78
For swift 4.X
let barButtonItem = UIBarButtonItem(title: "Click", style: .done, target: self, action: #selector(didClick(_:)))
barButtonItem.setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.blueColor()], forState: .normal)
barButtonItem.setTitleTextAttributes([NSAttributedStringKey.foregroundColor : UIColor.blueColor()], forState: .disabled)
barButtonItem.enabled = false
navigationItem.setRightBarButtonItem(barButtonItem, animated: false)
basically NSForegroundColorAttributeName
became NSAttributedStringKey.foregroundColor
and states went from being caps to lower case .Disabled
became .disabled
, etc..

- 876
- 1
- 8
- 23
Swift 5:
let barButtonItem = UIBarButtonItem(title: "Click", style: .done, target: self, action: #selector(didClick(_:)))
barButtonItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.blue], for: .normal)
barButtonItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.blue], for: .disabled)
barButtonItem.isEnabled = false
navigationItem.setRightBarButton(barButtonItem, animated: false)

- 33,281
- 23
- 160
- 191

- 421
- 8
- 14