4

I have a UIButton inside a UIView, when the UIButton is selected I would like have a background colour of dark gray...is this possible?

UIView *toolbar = [[UIView alloc]initWithFrame:CGRectMake(10, 50, 40, 160)];
    [toolbar setBackgroundColor:[UIColor colorWithWhite: 0.70 alpha:0.5]];

    toolbar.layer.cornerRadius = 5;

    UIButton *penTool = [UIButton buttonWithType:UIButtonTypeCustom];
    penTool.frame = CGRectMake(5, 0, 30, 30);
    [penTool setImage:[UIImage imageNamed:@"pen-but" inBundle:currentBundle compatibleWithTraitCollection:nil] forState:UIControlStateNormal];
    [penTool addTarget:self action:@selector(drawButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    penTool.autoresizingMask = UIViewAutoresizingNone;
    penTool.exclusiveTouch = YES;
    penTool.tag = 1;

    [toolbar addSubview:penTool];
user979331
  • 11,039
  • 73
  • 223
  • 418
  • What's it doing or not doing now? You should explain that. – l'L'l Jun 07 '16 at 21:50
  • @user979331 have a look at answer with 'UIButtonTypeSystem' below and save yourself the trouble of re-inventing something SDK already offers! – Tarun Tyagi Jun 13 '16 at 11:04
  • 2
    this is quite simple dont know why other dont put duplicate link instead of given answer http://stackoverflow.com/questions/14523348/how-to-change-the-background-color-of-a-uibutton-while-its-highlighted – Nitin Gohel Jun 17 '16 at 09:24
  • i tried to flag it by this http://stackoverflow.com/questions/14523348/how-to-change-the-background-color-of-a-uibutton-while-its-highlighted but the bounty didn't let me do it :-/ , just unnecesseary overkill bounty – Ratul Sharker Jun 19 '16 at 12:53
  • @user979331 I make an approach with easy and natural API, check it out. – Edward Anthony Jun 19 '16 at 19:16

9 Answers9

7

What if you can do this?

[button setBackgroundColor:[UIColor greenColor] 
                  forState:UIControlStateSelected];

Let's give a great API for every state, not just selected, just like UIButton default API's ability to change image and title for every state.

BGButton.h

#import <UIKit/UIKit.h>

@interface BGButton : UIButton

- (void)setBackgroundColor:(UIColor *)backgroundColor 
                  forState:(UIControlState)state;

@end

BGButton.m

#import "BGButton.h"

@implementation BGButton {
    NSMutableDictionary *_stateBackgroundColor;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _stateBackgroundColor = [[NSMutableDictionary alloc] init];
    }
    return self;
}


- (void)setBackgroundColor:(UIColor *)backgroundColor {
    [super setBackgroundColor:backgroundColor];

   /*
    * If user set button.backgroundColor we will set it to 
    * normal state's backgroundColor.
    * Check if state is on normal state to prevent background being 
    * changed for incorrect state when updateBackgroundColor method is called.
    */
    if (self.state == UIControlStateNormal) {
        [self setBackgroundColor:backgroundColor forState:UIControlStateNormal];
    }
}

- (void)setBackgroundColor:(UIColor *)backgroundColor 
                  forState:(UIControlState)state {
    NSNumber *key = [NSNumber numberWithInt:state];
    [_stateBackgroundColor setObject:backgroundColor forKey:key];
}

/*
 * state is synthesized from other flags. So we can't use KVO 
 * to listen for state changes.
 */
- (void)setSelected:(BOOL)selected {
    [super setSelected:selected];
    [self stateDidChange];
}

- (void)setEnabled:(BOOL)enabled {
    [super setEnabled:enabled];
    [self stateDidChange];
}

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

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    [self stateDidChange];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    [self stateDidChange];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    [self stateDidChange];
}

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    [self stateDidChange];
}

- (void)stateDidChange {
    [self updateBackgroundColor];
}

- (void)updateBackgroundColor {
    NSNumber *key = [NSNumber numberWithInt:self.state];
    self.backgroundColor = [_stateBackgroundColor objectForKey:key];
}

@end


You can use it like the default UIButton API

BGButton *button = [[BGButton alloc] init];

[button setBackgroundColor:[UIColor greenColor] 
                  forState:UIControlStateSelected];

[button setBackgroundColor:[UIColor blueColor] 
                  forState:UIControlStateHighlighted];

[button setBackgroundColor:[UIColor orangeColor] 
                  forState:UIControlStateDisabled];

Even if you use

button.backgroundColor = [UIColor redColor];

You will stay safe, it will be translated into

[button setBackgroundColor:[UIColor redColor] 
                  forState:UIControlStateNormal];
Edward Anthony
  • 3,354
  • 3
  • 25
  • 40
2

if you have this code

[self.view addSubview:toolbar];

then just implement your button selector

-(void)drawButtonTapped:(UIButton*)button{

if (button.selected) {
    button.backgroundColor = [UIColor clearColor];
    button.selected = NO;
}else{
    button.backgroundColor = [UIColor darkGrayColor];
    button.selected = YES;
}
}
Jamil
  • 2,977
  • 1
  • 13
  • 23
2

I don't know why guys would go through such trouble when we have this functionality built-in inside UIButton. All you need to do is use UIButtonTypeSystem That's all.

[UIButton buttonWithType:UIButtonTypeSystem]

Seriously, there's nothing more to it. Have a look at it's behavior in the screenshots.

INTERFACE BUILDER

STORYBOARD

RUN TIME

SIMULATOR

Want to change color, set tintColor to color of your choice.

ADVANTAGES

  • Covers titles with dynamic lengths. Not applied on all button width.
  • When selected, title color is transparent, your background can be seen through, try to use an image as a background.

Let's hope you have at least iOS7 as deployment target. UIButtonTypeSystem was introduce with revised UI design guidelines of iOS7 and has been there for almost 3 years.

Good Luck!

Community
  • 1
  • 1
Tarun Tyagi
  • 9,364
  • 2
  • 17
  • 30
2

I used a UIButton subclass here:

#import "CustomButton.h"

@interface CustomButton()
@property (nonatomic,strong) UIColor *originalColor;
@end

@implementation CustomButton

- (void)didMoveToSuperview
{
    self.originalColor = self.superview.backgroundColor;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.superview.backgroundColor = [UIColor grayColor];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInView:self];
    if ([self hitTest:location withEvent:nil]) {
        self.superview.backgroundColor = [UIColor grayColor];
        self.originalColor = self.superview.backgroundColor;
    }
    else
    {
        self.superview.backgroundColor = self.originalColor;
    }
}

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.superview.backgroundColor = self.originalColor;    
}

@end

If you subclass your button from this class, It should give you the desired effect. This also gives you the highlight effect. If you wish you can disable it by removing the line on touchesBegan.

  • 2
    if the guy who downvoted all the answers could care to add an explanation why he downvoted, maybe we could try to improve our answers.. – Murat Tezyapar Jun 14 '16 at 16:23
  • 2
    He is probably just trying to get the bounty to himself. You have the correct answer. `UIButton` is a subclass of `UIView`. OP can just override the `touchesBegan` and `touchesCancelled` methods to do whatever he wants. – JoeVictor Jun 18 '16 at 22:47
0

Just try to Override the UIButton with the following Method...

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

    if (highlighted) {
        self.backgroundColor = [UIColor darkGray];
    }

}
Suraj Sukale
  • 1,778
  • 1
  • 12
  • 19
0

I think you'll be want to change the selectedImage for flexibility not the background.

Add another image (e.g. pen-but-selected) in the project. Add this 2nd line for setImage:

[penTool setImage:[UIImage imageNamed:@"pen-but-selected" inBundle:currentBundle compatibleWithTraitCollection:nil] forState:UIControlStateSelected];

- (void)drawButtonTapped:(UIButton *)button {
    button.selected = !button.selected;
}

If you still want to change background color. @jamil's answer would work. Make sure the buttonImage has transparent part so you can see the buttonBackground through the buttonImage.

Warif Akhand Rishi
  • 23,920
  • 8
  • 80
  • 107
0

Try using a boolean, or some other reference to the selection state of the button. You could also make use of a 'highlightColour' as well as the 'selectedColour' if you wanted closer control (should probably do this for better UX).

bool buttonIsSelected = false;

UIColor * selectedColour = [UIColor redColor];
UIColor * defaultColour = [UIColor blueColor];

UIButton * button = [UIButton new];
button.frame = CGRectMake(0,0,100,100);
button.backgroundColor = [UIColor redColor];
[self.view addSubview:button];

[button addTarget:self action:@selector(buttonTouchUp:) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:@selector(buttonTouchCancel:) forControlEvents:UIControlEventTouchCancel];
[button addTarget:self action:@selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];

-(void)buttonTouchUp:(UIButton *)button {

    if (buttonIsSelected){
        buttonIsSelected = false;
        button.backgroundColor = defaultColour;
    } else {
        buttonIsSelected = true;
        button.backgroundColor = selectedColour;
    }
}
-(void)buttonTouchCancel:(UIButton *)button {
    button.backgroundColor = defaultColour;        
    if (buttonIsSelected){
        button.backgroundColor = selectedColour;
    }
}
-(void)buttonTouchDown:(UIButton *)button {
    button.backgroundColor = selectedColour;
}
Johnny Rockex
  • 4,136
  • 3
  • 35
  • 55
  • why the down vote mate? I admit, not the most elegant code, but in terms of fine control, and the ability to use the boolean in other bits (which presuming we need a highlight state, exist) it's ok, no? – Johnny Rockex Jun 20 '16 at 17:53
0
-(void)OnSelect:(UIButton*)button{

if (button.selected) {
    button.backgroundColor = [UIColor blue];
    button.selected = NO;
}else{
    button.backgroundColor = [UIColor darkGrayColor];
    button.selected = YES;
}
}

use the above this will work..

-1

-(void)buttonTapped:(UIButton*)button{

button.selected =! button.selected;

if (button.selected)
    button.backgroundColor = [UIColor grayColor];

else
    button.backgroundColor = [UIColor clearColor];

}