27

I have a method that creates a custom UIButton that allows me to change the color of the button using QuartzCore. But the buttons don't highlight when touched.

- (UIButton *)makeHeaderButton {
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    UIFont *textFont = [UIFont boldSystemFontOfSize:12];
    UIColor *textColor = [UIColor colorWithRed:80/255.0 green:109/255.0 blue:145/255.0 alpha:1.0];
    UIColor *backgroundColor = [UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1.0];
    [button setTitleColor:textColor forState:UIControlStateNormal];
    button.titleLabel.font = textFont;
    button.autoresizesSubviews = YES;
    button.layer.cornerRadius = 8;
    button.layer.borderWidth = 1;
    // next 2 properties set using QuartzCore class, no other way to set button colors
    button.layer.borderColor = [UIColor grayColor].CGColor;
    button.layer.backgroundColor = backgroundColor.CGColor;
    button.clipsToBounds = YES;
    return button;
}

How can I make these buttons highlight like a regular round rect button?

Bob
  • 559
  • 1
  • 5
  • 18

8 Answers8

25

In Swift, you can also override the isHighlighted var and add an alpha animation on it.

override var isHighlighted: Bool {
    didSet {
        UIView.animate(withDuration: 0.25, delay: 0, options: [.beginFromCurrentState, .allowUserInteraction], animations: {
            self.alpha = self.isHighlighted ? 0.5 : 1
        }, completion: nil)
    }
}
GrizzlyBear
  • 1,098
  • 1
  • 13
  • 27
  • 9
    When you tap & hold `isHighlighted` generates a lot of duplicated events. Therefore, it's best to check first if the value changed: `guard oldValue != self.isHighlighted else { return }` – Wojciech Kulik May 13 '19 at 09:07
13

In your code, add the line button.showsTouchWhenHighlighted = TRUE;

Garrett
  • 5,580
  • 2
  • 31
  • 47
  • 1
    That just seems to make the title fade out and in. I want the button background to flash to a blue color when the button is touched. – Bob Dec 30 '12 at 20:27
  • 1
    @Bob You could always set up a manual highlighting. For example: Register for an event `onTouchDown` (or whatever it is) and then in the implementation do something like `button.layer.backgroundColor = [UIColor BlueColor];` Then `onTouchUp` change the color back to your setting – Garrett Dec 30 '12 at 20:35
  • 8
    Wow, this is getting complicated. All I want to do is make a RoundRect button with a custom background color. Surely there is a simpler way to do this. – Bob Dec 31 '12 at 20:26
  • 2
    I ended put making a png file with the background color I wanted and then used setBackgroundImage:forState: to change the color of the roundRect button. – Bob Dec 31 '12 at 21:00
  • 1
    @Bob hard to believe there is no way to set button background color in highlight state :( – onmyway133 Dec 04 '13 at 17:15
9

For Swift, create a custom class that inherits from UIButton and override isHighlighted property:

class ButtonWithHighlight: UIButton {

    override var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }
        set {
            if newValue {
                backgroundColor = <#color when highlighted#>
            }
            else {
                backgroundColor = <#color for normal state#>
            }
            super.isHighlighted = newValue
        }
    }

}
jvrmed
  • 834
  • 6
  • 12
  • manipulating alpha rather than backgroundColor seems to work better – Anton Tropashko May 23 '19 at 12:36
  • @AntonTropashko that might be better if the highlight colour is the same as the normal state one, it wouldn't work for cases when you want a white normal button and a green highlighted one – jvrmed May 24 '19 at 13:04
6

If someone still encounters the problem - you should create UIButton like this:

UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];

btn.layer.cornerRadius = 4;
btn.layer.masksToBounds = YES;

[btn setTranslatesAutoresizingMaskIntoConstraints:NO];

[btn setBackgroundColor:[UIColor greenColor]];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

[btn setTitle:@"ok" forState:UIControlStateNormal];

*** any customisation that you would like ***

[parentView addSubview: btn];

So this way you still have iOS taking care of all highlighting. The main thing is using

[UIButton buttonWithType:UIButtonTypeSystem];

If you use initWithFrame or any other method - you would have to implement

setTitleColor: forState: 
setBackgroundImage: forState:
quarezz
  • 454
  • 1
  • 6
  • 11
  • 2
    Using a System button vs a Custom button is the key. Even if the button is created on a Storyboard or Nib. In IB, setting an image on the button changes it to a custom button, so you need to change it back manually. – Dave Wood Jul 19 '16 at 10:56
4

You can create your own subclass of UIButton (then you simply set all thoses properties in the constructor).

And you must override the highlight method of UIButton

- (void)setHighlighted:(BOOL)highlighted {
    if (highlighted) {
        self.backgroundColor = [UIColor redColor];
    } else {
        self.backgroundColor = [UIColor blueColor];
    }
}
KIDdAe
  • 2,714
  • 2
  • 22
  • 29
0

Based on answer by @jvrmed.

I have achieved highlight functionality by changing the alpha values of title and button. My custom button has same background color in normal and highlighted mode, but you can add different colors as well.

Here is the code

class CustomButton: UIButton {

   private let primaryTitle: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        return label
   }()
       
   override var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }
        set {
            if newValue {
                primaryTitle.alpha = 0.5
                alpha = 0.8
            }
            else {
                primaryTitle.alpha = 1.0
                alpha = 1.0
            }
            super.isHighlighted = newValue
        }
    }
    
    // Add title as subview and set frame in layoutSubviews method
    
}

It works like this, you can tweak the alpha values as per your need.

enter image description here

Sunny
  • 821
  • 6
  • 17
-1

There is easy way to implement highlight on custom button. 1. create .png image for highlight state (with color, alpha, etc.); 2. go to yourbutton.xib; 3. select Attributes Inspector on the right of XCode; 4. set State Config as Highlighted 5. set you .png image as Background image. You are welcome :)

Vanja Dev
  • 197
  • 1
  • 8
-6

In Storyboard set the button background default image and highlighted image. on Button action write this line i.e. change the button colour for 1 second

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];