18

I'm having an issue with a UIBarButtonItem. I use the appearance proxy to set its color for states Normal and Disabled and I do this in the viewDidLoad method of the UIViewController. However, the button gets the Normal color, even when it is disabled (and it is definitely disabled because the IBAction method is not being called).

The question is similar to this one text color of disabled uibarbuttonitem is always the color of the normal state, however, the solution posted here does not work for me.

My app is for iOS 8.2 and I'm using Xcode 6.2

Any ideas?

EDIT: I am not sure if this is helpful for finding the solution, but when I create my button using initWithImage: instead of initWithTitle: everything seems to be working well. Could this be an Apple bug?

Community
  • 1
  • 1
Banana
  • 4,010
  • 9
  • 33
  • 49
  • Can you please post your code where you use the appearance proxy to set its color for states? – jakedunc Mar 20 '15 at 14:12
  • I create the button programmatically viewDidLoad, I add is at the rightBarButtonItem to my navigationBar, and then I call the appearance proxy. – Banana Mar 20 '15 at 14:17

6 Answers6

36

Swift 4

If someone looking for how to change barbuttonitem disabled state appearance in swift. Here you go.

barButtonItem.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.lightGray], for: .disabled)
Community
  • 1
  • 1
Swift Hipster
  • 1,604
  • 3
  • 16
  • 24
7

Check with following code.

- (void)viewDidLoad {
    [super viewDidLoad];

    UIBarButtonItem * btnTemp = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnDone_Click:)];
    [btnTemp setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor lightGrayColor], NSFontAttributeName:[UIFont boldSystemFontOfSize:16.0f]} forState:UIControlStateNormal];

    [btnTemp setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blueColor], NSFontAttributeName:[UIFont systemFontOfSize:16.0f]} forState:UIControlStateDisabled];

    [self.navigationItem setRightBarButtonItem:btnTemp];

}

- (void)btnDone_Click : (id)sender {

    UIBarButtonItem * button = (UIBarButtonItem *)sender;
    [button setEnabled:FALSE];
    [self performSelector:@selector(enableButton:) withObject:sender afterDelay:2.0f];


}

- (void)enableButton : (id)sender {
    UIBarButtonItem * button = (UIBarButtonItem *)sender;
    [button setEnabled:TRUE];
}
Abhishek Sharma
  • 3,283
  • 1
  • 13
  • 22
  • above code i settled out button color in your given state.. And after your tap it will disable and after 2 second enable again so you can check it again... – Abhishek Sharma Mar 23 '15 at 09:45
  • My button is initially disabled, so this does not work for me. The problem is not the state of the button, the state is correct since the onClick selector is never invoked. It's just the problem with the color, i.e. the button has the enabled color, but it cannot be clicked. – Banana Mar 23 '15 at 11:01
5

So I finally managed to get this working as it should, and the problem was that I was setting the color of UIBarButtonItems twice, once using [navBar setTintColor:] and once using the appearance proxy. Leaving just the appearance proxy solves the problem.

Banana
  • 4,010
  • 9
  • 33
  • 49
  • removing code to fix an issue is always better than adding more code to fix it, glad you found this solution :) – Ilias Karim Jan 26 '16 at 23:02
2

You have likely set the bar button item title text attributes for the .Normal state and need to also set it for the .Disabled state.

There are two ways to fix this, one if you are setting the title text attributes on the bar button item instance and in the other case if you use the appearance proxy.

Single instance:

saveButton.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.grayColor()], forState: .Disabled)

Appearance proxy:

UIBarButtonItem.appearanceWhenContainedInInstancesOfClasses([MyNavigationController.self]).setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.grayColor()], forState: .Disabled)
Kyle Clegg
  • 38,547
  • 26
  • 130
  • 141
  • This is great, but other controls like `UIButton` calculate the disabled state tint color automatically as a lighter version of the normal one. How can I use appearance proxies and have **consistent**, **disabled** title color between both `UIButton` and `UIBarButtonItem`? `UIButton`'s appearance proxy does not respond to `setTitleTextAttributes`... – Nicolas Miari Feb 03 '17 at 05:44
1

This updates the answer for Swift 4.0:

barButtonItem.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.gray], for: UIControlState.disabled)

This shows an illustrative example of an orange color for disabled against a white barTintColor:

enter image description here

barTintColor = .white    
cancelButton.isEnabled = false
cancelButton.setTitleTextAttributes(
    [NSAttributedStringKey.foregroundColor: UIColor.orange], 
    for: UIControlState.disabled)
CodeBender
  • 35,668
  • 12
  • 125
  • 132
0

This was also my issue, when running on iOS versions 10.*. Setting the button's foreground color solved the issue for me.

self.saveButton.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.gray], for: UIControlState.disabled)
tab67
  • 29
  • 2