40

I created a navigation button in my UINavigationController. I set it to be highlighted when touched:

[someButton setShowsTouchWhenHighlighted:YES];

Is there a way to change the highlighted color to something other than the default white?

Code Monkey
  • 968
  • 1
  • 14
  • 26

8 Answers8

49

Try to Override the UIButton with the following Method.. and just change the backgroud color of button when its in highlighted state.

- (void)setHighlighted:(BOOL)highlighted {
    [super setHighlighted:highlighted];

    if (highlighted) {
        self.backgroundColor = [UIColor Your Customcolor];
    }
    else{
        self.backgroundColor = [UIColor Your DefaultColor];
    }   

}

Try it..hope it helps

Rubaiyat Jahan Mumu
  • 3,887
  • 1
  • 33
  • 35
BhavikKama
  • 8,566
  • 12
  • 94
  • 164
48

You can use setBackgroundImage:forState: to set the background image for the button when highlighted.

ex:

As suggested by Tim in their answer here, you can create aUIImage from UIColor:

- (UIImage *)imageWithColor:(UIColor *)color {
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Then set image as button's background image when highlighted

[button setBackgroundImage:[self imageWithColor:[UIColor blueColor]] forState:UIControlStateHighlighted];

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
bradley
  • 648
  • 5
  • 6
24

In Swift:

import UIKit

class CustomUIButtonForUIToolbar: UIButton {

    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
        super.drawRect(rect)

        self.layer.borderColor = UIColor.blueColor().CGColor
        self.layer.borderWidth = 1.0
        self.layer.cornerRadius = 5.0
        self.clipsToBounds = true
        self.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)

        self.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Highlighted)
    }

    override var highlighted: Bool {
        didSet {

            if (highlighted) {
                self.backgroundColor = UIColor.blueColor()
            }
            else {
                self.backgroundColor = UIColor.clearColor()
            }

        }
    }

}
King-Wizard
  • 15,628
  • 6
  • 82
  • 76
  • 4
    FYI none of that code should be in `drawRect`. `drawRect` is for drawing to a graphics context. I'd personally put those into `awakeFromNib` but `init?(coder:)` also works. – Christopher Swasey Oct 29 '16 at 15:13
5

I'll provide a Swift answer, which can be used without any customization, if you want the highlighted color to be a darkened version of the original background color. If you, on the other hand, want a completely different highlighted background color, you can supply that to the highlightedBackgroundColor property as a UIColor.

The following is the most efficient and straightforward way to implement such a functionality in Swift. It is also generic, meaning it can be used for lots of different buttons with different colors.

Here's the code:

import UIKit

class HighlightedColorButton: UIButton {

    // A new highlightedBackgroundColor, which shows on tap
    var highlightedBackgroundColor: UIColor?
    // A temporary background color property, which stores the original color while the button is highlighted
    var temporaryBackgroundColor: UIColor?


    // Darken a color
    func darkenColor(color: UIColor) -> UIColor {

        var red = CGFloat(), green = CGFloat(), blue = CGFloat(), alpha = CGFloat()

        color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

        red = max(red - 0.5, 0.0)
        green = max(green - 0.5, 0.0)
        blue = max(blue - 0.5, 0.0)

        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
    }


    // Set up a property observer for the highlighted property, so the color can be changed
    @objc override var highlighted: Bool {
        didSet {
            if highlighted {
                if temporaryBackgroundColor == nil {
                    if backgroundColor != nil {
                        if let highlightedColor = highlightedBackgroundColor {
                            temporaryBackgroundColor = backgroundColor
                            backgroundColor = highlightedColor
                        } else {
                            temporaryBackgroundColor = backgroundColor
                            backgroundColor = darkenColor(temporaryBackgroundColor!)
                        }
                    }
                }
            } else {
                if let temporaryColor = temporaryBackgroundColor {
                    backgroundColor = temporaryColor
                    temporaryBackgroundColor = nil
                }
            }
        }
    }
}

Treat the button as a normal UIButton, with the addition of the optional property highlightedBackgroundColor:

let highlightedColorButton = HighlightedColorButton.buttonWithType(.Custom) as HighlightedColorButton
highlightedColorButton.backgroundColor = UIColor.redColor()
highlightedColorButton.highlightedBackgroundColor = UIColor.blueColor()
ArVID220u
  • 374
  • 3
  • 10
3

Use this statement to set the highlighted color of the UIButton:

[button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
Vinay Jain
  • 2,644
  • 3
  • 26
  • 44
1

In Swift, if you want to use a image for highlighted state, you can do this with UIButton:

if enabled {
 //highlighted state
     enableMicrophone.setImage(UIImage(named: "mic_on"), forState: .Highlighted)
 } else {
 //normal state
     enableMicrophone.setImage(UIImage(named: "mic_off"), forState: .Normal)    
}
CodeOverRide
  • 4,431
  • 43
  • 36
1

For Swift

import UIKit

extension UIImage {

func imageWithAlphaComponent(alpha: CGFloat) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, 0)

    let ctx = UIGraphicsGetCurrentContext()
    let area = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)

    CGContextScaleCTM(ctx, 1, -1)
    CGContextTranslateCTM(ctx, 0, -area.size.height)

    CGContextSetBlendMode(ctx, CGBlendMode.Multiply)

    CGContextSetAlpha(ctx, alpha)

    CGContextDrawImage(ctx, area, self.CGImage)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return newImage
}
}

Write

button.setImage(image.imageWithAlphaComponent(0.65), forState: .Highlighted)

https://gist.github.com/yukitoto/e8aa420e20be7ab5d64b71e96ecd61f1

0

I'm getting some success by using an old, old web trick.

I've created a couple of image assets in images.xcassets, PNG files, both 1px by 1px. One is the normal colour, the other is the background colour.

I'm going from pure black to pure white, so:

In the storyboard I select the button. In the 'Attributes inspector' (right-hand panel, 4th icon across) I change the type to 'custom', change the 'state config' to 'highlight', then 'background' to 'whitePixel' (or whatever you called it) and 'Text Color' to 'black color'.

Now I change the 'state config' to 'Default', the 'background' to 'blackPixel' (or whatever) and the 'Text Color' to 'white color'.

I guess you can use these pixels whenever you need to apply a colour when you only have access to images in the Storyboard editor.

This does increase the number of image assets, but reduces the required code hugely. Which pleases me.

A Fader Darkly
  • 3,516
  • 1
  • 22
  • 28