简体   繁体   中英

Change background color of UIButton when Highlighted

Hi I want to change the UIButton background color which user Tap on the button.

I am showing background color using gradient, when user tap I need to change the gradient color.

[btn setTitle: @"Next" forState:UIControlStateNormal];
CAGradientLayer *gradient = [CAGradientLayer layer];            
gradient.frame = btn.bounds;
gradient.cornerRadius = 10.0f;
locations = [[NSArray alloc] initWithObjects: 0.0f, 0.0f, 0.0f,0.0f, nil]; 
[gradient setLocations:locations];
colorNext = [[NSArray alloc] initWithObjects:…., nil]; 
gradient.colors = colorNext;
[locations release];
[btn.layer insertSublayer:gradient atIndex:0];
btn.titleLabel.textColor = [UIColor blackColor];

Changing the internal layer hierarchy of a UIButton is not recommended since it may break in a future update of the iOS. Also, it may cause Apple to reject your application. A better solution would be to create a button subclass. Here is an example of how to do it:

@interface MyButton : UIButton
@end

@implementation MyButton

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        [self addObserver:self forKeyPath:@"highlighted" options:NSKeyValueObservingOptionNew context:NULL];
    }

    return self;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    if (self.highlighted == YES)
    {
        CGContextRef ctx = UIGraphicsGetCurrentContext();

        CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();

        const CGFloat *topGradientColorComponents = CGColorGetComponents([UIColor whiteColor].CGColor);
        const CGFloat *bottomGradientColorComponents = CGColorGetComponents([UIColor blackColor].CGColor);

        CGFloat colors[] =
        {
            topGradientColorComponents[0], topGradientColorComponents[1], topGradientColorComponents[2], topGradientColorComponents[3],
            bottomGradientColorComponents[0], bottomGradientColorComponents[1], bottomGradientColorComponents[2], bottomGradientColorComponents[3]
        };
        CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, NULL, sizeof(colors) / (sizeof(colors[0]) * 4));
        CGColorSpaceRelease(rgb);

        CGContextDrawLinearGradient(ctx, gradient, CGPointMake(0, 0), CGPointMake(0, self.bounds.size.height), 0);
        CGGradientRelease(gradient);
    }
    else
    {
        // Do custom drawing for normal state
    }
}

- (void)dealloc
{
    [self removeObserver:self forKeyPath:@"highlighted"];

    [super dealloc];
}

@end

You may need to modify it a bit to get it to do what you want but I think you get the basic idea.

Try this:

[Button addTarget:self action:@selector(doSomething:) forControlEvents:UIControlEventTouchUpInside];
[Button addTarget:self action:@selector(setBgColorForButton:) forControlEvents:UIControlEventTouchDown];
[Button addTarget:self action:@selector(clearBgColorForButton:) forControlEvents:UIControlEventTouchDragExit];

-(void)setBgColorForButton:(UIButton*)sender
{
    [sender setBackgroundColor:[UIColor blackColor]];
}

-(void)clearBgColorForButton:(UIButton*)sender
{
    [sender setBackgroundColor:[UIColor redColor]];
}

-(void)doSomething:(UIButton*)sender
{
double delayInSeconds = 0.3;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [sender setBackgroundColor:[UIColor redColor]];
    });
    //do something

}

You can use this method to create and solid UIImage of specified color and then apply it to your button. I've made a category for UIImage to do this.

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size
{
    UIGraphicsBeginImageContext(size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, (CGRect){.size = size});

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

    return image;
}

+ (UIImage *)imageWithColor:(UIColor *)color
{
    return [UIImage imageWithColor:color size:CGSizeMake(1, 1)];
}

Usage:

[button setBackgroundImage:[UIImage imageWithColor:[UIColor redColor]]
                  forState:UIControlStateNormal];

As Matthias pointed out, you can safely use 1x1 image for your button background – it will be stretched to fill the button.

I found this AYUIButton on GitHub and it works perfectly :) Here is sample code:

[btn setBackgroundColor:[UIColor redColor] forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor blueColor] forState:UIControlStateHighlighted];

当您设置按钮的TintColor时,它会在突出显示时起作用

[YourButton setTintColor:[UIColor color]];

Swift

Extension for UIButton that let you specify background color for each state:

https://github.com/acani/UIButtonBackgroundColor

Please note that for iphone 6 plus you should change the following, inside the extension in the .swift class, that will fix it for all the versions:

//let rect = CGRect(x: 0, y: 0, width: 0.5, height: 0.5) comment this line
    let rect = CGRect(x: 0, y: 0, width: 1, height: 1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM