163

In my iPhone app, I have a UIButton which I have created in Interface Builder. I can successfully enable and disable it like this in my code ...

sendButton.enabled = YES;

or

sendButton.enabled = NO;

However, the visual look of the button is always the same! It is not faded or grey. If I attempt to click it though, it is enabled or disabled as expected. Am I missing something? Shouldn't it look faded or grey?

phimuemue
  • 34,669
  • 9
  • 84
  • 115
Andy A
  • 4,191
  • 7
  • 38
  • 56

19 Answers19

217

You can use following code:

sendButton.enabled = YES;
sendButton.alpha = 1.0;

or

sendButton.enabled = NO;
sendButton.alpha = 0.5;
FormigaNinja
  • 1,571
  • 1
  • 24
  • 36
Ravin
  • 8,544
  • 3
  • 20
  • 19
  • 13
    While this works I reckon solutions that change the look depending on control state like [this](http://stackoverflow.com/a/5715366/2547229) and [this](http://stackoverflow.com/a/14543996/2547229) from below are a much better idea. They're using the built in mechanism to achieve an automatic change, rather than needing to explicitly update the control's look depending on its state. – Benjohn Jul 06 '15 at 15:15
87

just change state config to disable and choose what you want, background Image for disabled state

enter image description here

Ahmed R.
  • 1,209
  • 1
  • 12
  • 22
  • 22
    This only changes properties in the **Button** sub heading. Background color is under the **View** subheading, so isn't changed by state configs. – Hunter Monk Nov 07 '16 at 17:43
  • 2
    This is not working for view's background color. In my project I combined previous answer and this. – Anton Mar 20 '17 at 07:05
  • I'm using Xcode 14 and for this version you need to set the button style to "Default" before you can see the 'State Config' item. – ThomasW May 11 '23 at 06:33
50

Another option is to change the text color (to light gray for example) for the disabled state.

In the storyboard editor, choose Disabled from the State Config popup button. Use the Text Color popup button to change the text color.

In code, use the -setTitleColor:forState: message.

pkamb
  • 33,281
  • 23
  • 160
  • 191
guywithmazda
  • 757
  • 7
  • 10
  • 1
    This seems like a much better solution than the excepted answer of adjusting the alpha. I'd already voted this up months ago and now I'm back here with the same problem, I wish I could do it again! – Benjohn Jul 06 '15 at 15:12
  • Yep, seems to be a working solution. I just use the light gray color. – atereshkov Jul 18 '18 at 07:49
34

To make the button is faded when disable, you can set alpha for it. There are two options for you:

First way: If you want to apply for all your buttons in your app, so you can write extension for UIButton like this:

extension UIButton {

    open override var isEnabled: Bool{
        didSet {
            alpha = isEnabled ? 1.0 : 0.5
        }
    }

}

Second way: If you just want to apply for some buttons in your app, so you can write a custom class from UIButton like below and use this class for which you want to apply:

class MyButton: UIButton {
    override var isEnabled: Bool {
        didSet {
            alpha = isEnabled ? 1.0 : 0.5
        }
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Heo Đất Hades
  • 1,573
  • 18
  • 14
23

Try to set the different images for UIControlStateDisabled (disabled gray image) and UIControlStateNormal(Normal image) so the button generate the disabled state for you.

Jhaliya - Praveen Sharma
  • 31,697
  • 9
  • 72
  • 76
  • 2
    he's not using images--but you could apply this same concept to `[ UIButton setAttributedTitle:forState:]`. Create your attributed string where your text foreground color is set to a transparent color. – nielsbot May 20 '13 at 23:33
14

If you use a text button, you can put into viewDidLoad the instance method

- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state

example:

[self.syncImagesButton setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
Antonio Moro
  • 154
  • 2
  • 4
  • 1
    This should be the accepted answer for a text button.. Current accepted answer is good for an image button. What I get from op's comments is that he has a text button.. – Ali Hus May 10 '19 at 13:04
14

You can use adjustsImageWhenDisabled which is property of UIButton
(@property (nonatomic) BOOL adjustsImageWhenDisabled)

Ex:

 Button.adjustsImageWhenDisabled = false
Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
Mahesh Lad
  • 169
  • 1
  • 3
10

Set title color for different states:

@IBOutlet weak var loginButton: UIButton! {
        didSet {
            loginButton.setTitleColor(UIColor.init(white: 1, alpha: 0.3), for: .disabled)
            loginButton.setTitleColor(UIColor.init(white: 1, alpha: 1), for: .normal)
        }
    }

Usage: (text color will get change automatically)

loginButton.isEnabled = false

enter image description here

Kiran S
  • 403
  • 8
  • 13
9

This is quite an old question but there's a much simple way of achieving this.

myButton.userInteractionEnabled = false

This will only disable any touch gestures without changing the appearance of the button

Diego A. Rincon
  • 747
  • 1
  • 8
  • 25
  • 2
    I think OP has the opposite problem. They are already changing this flag but _want_ the appearance to change. – qu1j0t3 Feb 19 '21 at 20:32
9

Swift 4+

extension UIButton {
    override open var isEnabled: Bool {
        didSet {
            if self.isEnabled {
                self.alpha = 1.0
            }
            else {
                self.alpha = 0.5
            }
            //make sure button is updated
            self.layoutIfNeeded()
        }
    }
}

How to use

myButton.isEnabled = false
Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Rashid Latif
  • 2,809
  • 22
  • 26
6

In Swift:

previousCustomButton.enabled = false
previousCustomButton.alpha = 0.5

or

nextCustomButton.enabled = true
nextCustomButton.alpha = 1.0
King-Wizard
  • 15,628
  • 6
  • 82
  • 76
4

You can use the both first answers and is going to be a better result.

In the attribute inspector (when you're selecting the button), change the State Config to Disabled to set the new Image that is going to appear when it is disabled (remove the marker in the Content->Enabled check to made it disabled).

And when you change the state to enabled, the image will load the one from this state.

Adding the alpha logic to this is a good detail.

pkamb
  • 33,281
  • 23
  • 160
  • 191
ChavirA
  • 707
  • 8
  • 18
4

Create an extension in Swift > 3.0 rather than each button by itself

extension UIButton {
    override open var isEnabled : Bool {
        willSet{
            if newValue == false {
                self.setTitleColor(UIColor.gray, for: UIControlState.disabled)
            }
        }
    }
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
iosMentalist
  • 3,066
  • 1
  • 30
  • 40
3

It looks like the following code works fine. But in some cases, this doesn't work.

sendButton.enabled = NO;
sendButton.alpha = 0.5;

If the above code doesn't work, please wrap it in Main Thread. so

dispatch_async(dispatch_get_main_queue(), ^{
    sendButton.enabled = NO;
    sendButton.alpha = 0.5
});

if you go with swift, like this

DispatchQueue.main.async {
    sendButton.isEnabled = false
    sendButton.alpha = 0.5
}

In addition, here I write UIButton extension functions.

extension UIButton {
    func enable() {
        DispatchQueue.main.async {
            self.isEnabled = true
            self.alpha = 1.0
        }
    }

    func disable() {
        DispatchQueue.main.async {
            self.isEnabled = false
            self.alpha = 0.5
        }
    }
}

Thank you and enjoy coding!!!

Li Jin
  • 1,879
  • 2
  • 16
  • 23
2

I am stuck on the same problem. Setting alpha is not what I want.

UIButton has "background image" and "background color". For image, UIButton has a property as

@property (nonatomic) BOOL adjustsImageWhenDisabled

And background image is drawn lighter when the button is disabled. For background color, setting alpha, Ravin's solution, works fine.

First, you have to check whether you have unchecked "disabled adjusts image" box under Utilities-Attributes.
Then, check the background color for this button.

(Hope it's helpful. This is an old post; things might have changed in Xcode).

Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
Yichao Lu
  • 53
  • 5
2

If the UIButton is in the combined state of selected and disabled, its state is UIControlStateSelected | UIControlStateDisabled.

So its state needs to be adjusted like this:

[button setTitleColor:color UIControlStateSelected | UIControlStateDisabled];
[button setImage:image forState:UIControlStateSelected | UIControlStateDisabled];

One approach is to subclass UIButton as follows:

@implementation TTButton
- (void)awakeFromNib {
   [super awakeFromNib];

    //! Fix behavior when `disabled && selected`
    //! Load settings in `xib` or `storyboard`, and apply it again.
    UIColor *color = [self titleColorForState:UIControlStateDisabled];
    [self setTitleColor:color forState:UIControlStateDisabled];

    UIImage *img = [self imageForState:UIControlStateDisabled];
    [self setImage:img forState:UIControlStateDisabled];
}

- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state {
    [super setTitleColor:color forState:state];

    //
    if (UIControlStateDisabled == state) {
        [super setTitleColor:color forState:UIControlStateSelected | state];
        [super setTitleColor:color forState:UIControlStateHighlighted | state];
    }
}

- (void)setImage:(UIImage *)image forState:(UIControlState)state {
    [super setImage:image forState:state];

    if (UIControlStateDisabled == state) {
        [super setImage:image forState:UIControlStateSelected | state];
        [super setImage:image forState:UIControlStateHighlighted | state];
    }
}

@end
Lennart Wisbar
  • 322
  • 1
  • 11
AechoLiu
  • 17,522
  • 9
  • 100
  • 118
  • 1
    This should be the accepted answer. On Swift you will need something like setTitleColor(disabledColor, for: [.disabled, .selected]) – Paulo Cesar Oct 25 '18 at 12:40
2

Maybe you can subclass your button and override your isEnabled variable. The advantage is that you can reuse in multiple places.

override var isEnabled: Bool {
     didSet {
         if isEnabled {
             self.alpha = 1
         } else {
             self.alpha = 0.2
         }
     }
 }
Jay Mayu
  • 17,023
  • 32
  • 114
  • 148
1

This question has a lot of answers but all they looks not very useful in case if you really want to use backgroundColor to style your buttons. UIButton has nice option to set different images for different control states but there is not same feature for background colors. So one of solutions is to add extension which will generate images from color and apply them to button.

extension UIButton {
  private func image(withColor color: UIColor) -> UIImage? {
    let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
    UIGraphicsBeginImageContext(rect.size)
    let context = UIGraphicsGetCurrentContext()

    context?.setFillColor(color.cgColor)
    context?.fill(rect)

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image
  }

  func setBackgroundColor(_ color: UIColor, for state: UIControlState) {
    self.setBackgroundImage(image(withColor: color), for: state)
  }
}

Only one issue with this solution -- this change won't be applied to buttons created in storyboard. As for me it's not an issue because I prefer to style UI from code. If you want to use storyboards then some additional magic with @IBInspectable needed.

Second option is subclassing but I prefer to avoid this.

oroom
  • 1,318
  • 11
  • 10
-1
#import "UIButton+My.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIButton (My)


-(void)fade :(BOOL)enable{
    self.enabled=enable;//
    self.alpha=enable?1.0:0.5;
}

@end

.h:

#import <UIKit/UIKit.h>
@interface UIButton (My)

-(void)fade :(BOOL)enable;

@end