Comment changer la couleur de fond d'un UIButton pendant qu'il est surligné?

à un moment donné dans mon application j'ai mis en surbrillance UIButton (par exemple quand un utilisateur a son doigt sur le bouton) et je dois changer la couleur de fond pendant que le bouton est mis en surbrillance (donc pendant que le doigt de l'utilisateur est encore sur le bouton).

j'ai essayé la suivante:

_button.backgroundColor = [UIColor redColor];

mais ça ne marche pas. La couleur reste la même. J'ai essayé le même morceau de code quand le bouton n'est pas surligné et il fonctionne très bien. J'ai aussi essayé d'appeler -setNeedsDisplay après avoir changé la couleur, il n'a pas eu d'effet.

comment forcer le bouton pour changer la couleur de fond?

202
demandé sur Gabriel.Massana 2013-01-25 18:04:22

27 réponses

vous pouvez remplacer UIButton 's setHighlighted méthode.

Objectif-C

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

    if (highlighted) {
        self.backgroundColor = UIColorFromRGB(0x387038);
    } else {
        self.backgroundColor = UIColorFromRGB(0x5bb75b);
    }
}

Swift 3.0 et Swift 4.1

override open var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? UIColor.black : UIColor.white
    }
}
346
répondu Thomas Decaux 2018-07-10 02:18:04

Je ne suis pas sûr que ce genre de solution résolve ce que vous recherchez, ou s'adapte à votre paysage de développement général, mais la première chose que je voudrais essayer serait de changer la couleur de fond du bouton sur l'événement touchDown.

Option 1:

vous auriez besoin de deux événements pour être capturé, UIControlEventTouchDown serait pour lorsque l'utilisateur appuie sur le bouton. L'uicontreleventtouchupinside et L'Uicontreleventtouchupoutside seront quand ils relâchez le bouton pour revenir à l'état normal

UIButton *myButton =  [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setFrame:CGRectMake(10.0f, 10.0f, 100.0f, 20.f)];
[myButton setBackgroundColor:[UIColor blueColor]];
[myButton setTitle:@"click me:" forState:UIControlStateNormal];
[myButton setTitle:@"changed" forState:UIControlStateHighlighted];
[myButton addTarget:self action:@selector(buttonHighlight:) forControlEvents:UIControlEventTouchDown];
[myButton addTarget:self action:@selector(buttonNormal:) forControlEvents:UIControlEventTouchUpInside];

Option 2:

retourner une image faite à partir de la couleur de surbrillance que vous voulez. Cela pourrait aussi être une catégorie.

+ (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;
}

et ensuite changer l'état surligné du bouton:

[myButton setBackgroundImage:[self imageWithColor:[UIColor greenColor]] forState:UIControlStateHighlighted];
292
répondu Tim 2017-04-05 03:07:39

il n'est pas nécessaire de remplacer highlighted comme bien calculé. Vous pouvez utiliser la propriété observer pour déclencher le changement de couleur de fond:

override var highlighted: Bool {
    didSet {
        backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor()
    }
}

Swift 4

override var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white
    }
}
87
répondu Aleksejs Mjaliks 2018-03-26 04:57:37

dans swift, vous pouvez outrepasser l'accessor de la propriété highlighted (ou selected) plutôt que la méthode setHighlighted

override var highlighted: Bool {
        get {
            return super.highlighted
        }
        set {
            if newValue {
                backgroundColor = UIColor.blackColor()
            }
            else {
                backgroundColor = UIColor.whiteColor()
            }
            super.highlighted = newValue
        }
    }
44
répondu Jake Hall 2014-10-07 17:54:25

une extension générique pratique dans Swift:

extension UIButton {
    private func imageWithColor(color: UIColor) -> UIImage {
        let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()

        CGContextSetFillColorWithColor(context, color.CGColor)
        CGContextFillRect(context, rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image
    }

    func setBackgroundColor(color: UIColor, forUIControlState state: UIControlState) {
        self.setBackgroundImage(imageWithColor(color), forState: state)
    }
}

Swift 3.0

extension UIButton {
    private func imageWithColor(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(imageWithColor(color: color), for: state)
    }
}
38
répondu Giordano Scalzo 2017-11-03 13:16:46

remplace la variable surlignée. L'ajout de @IBInspectable vous permet d'éditer la couleur de fond en surbrillance dans le storyboard, ce qui est aussi astucieux.

class BackgroundHighlightedButton: UIButton {
    @IBInspectable var highlightedBackgroundColor :UIColor?
    @IBInspectable var nonHighlightedBackgroundColor :UIColor?
    override var highlighted :Bool {
        get {
            return super.highlighted
        }
        set {
            if newValue {
                self.backgroundColor = highlightedBackgroundColor
            }
            else {
                self.backgroundColor = nonHighlightedBackgroundColor
            }
            super.highlighted = newValue
        }
    }
}
21
répondu mash 2015-02-03 07:51:26

une solution plus compacte (basée sur @aleksejs-mjaliks réponse):

Swift 3/4+ :

override var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? .lightGray : .white
    }
}

Swift 2:

override var highlighted: Bool {
    didSet {
        backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor()
    }
}
16
répondu Federico Zanetello 2018-07-11 07:13:32

extension UIButton avec Swift 3+ syntaxe:

extension UIButton {
    func setBackgroundColor(color: UIColor, forState: UIControlState) {
        UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
        UIGraphicsGetCurrentContext()!.setFillColor(color.cgColor)
        UIGraphicsGetCurrentContext()!.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
        let colorImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.setBackgroundImage(colorImage, for: forState)
    }}

utiliser comme:

YourButton.setBackgroundColor(color: UIColor.white, forState: .highlighted)

Réponse Originale: https://stackoverflow.com/a/30604658/3659227

12
répondu Maverick 2018-01-21 05:06:31

vous pouvez utiliser cette catégorie qui ajoute la méthode setBackgroundColor: forState:

https://github.com/damienromito/UIButton-setBackgroundColor-forState -

9
répondu Damien Romito 2015-01-22 16:00:25

Voici une approche dans Swift, en utilisant une extension UIButton pour ajouter un IBInspectable, appelé highlightedBackgroundColor. Semblable au sous-classement, sans exiger de sous-classe.

private var HighlightedBackgroundColorKey = 0
private var NormalBackgroundColorKey = 0

extension UIButton {

    @IBInspectable var highlightedBackgroundColor: UIColor? {
        get {
            return objc_getAssociatedObject(self, &HighlightedBackgroundColorKey) as? UIColor
        }

        set(newValue) {
            objc_setAssociatedObject(self,
                &HighlightedBackgroundColorKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }

    private var normalBackgroundColor: UIColor? {
        get {
            return objc_getAssociatedObject(self, &NormalBackgroundColorKey) as? UIColor
        }

        set(newValue) {
            objc_setAssociatedObject(self,
                &NormalBackgroundColorKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }

    override public var backgroundColor: UIColor? {
        didSet {
            if !highlighted {
                normalBackgroundColor = backgroundColor
            }
        }
    }

    override public var highlighted: Bool {
        didSet {
            if let highlightedBackgroundColor = self.highlightedBackgroundColor {
                if highlighted {
                    backgroundColor = highlightedBackgroundColor
                } else {
                    backgroundColor = normalBackgroundColor
                }
            }
        }
    }
}

j'espère que cela aidera.

9
répondu Fostah 2015-04-06 19:17:19

Mon meilleur solution pour les "151930920 Swift" 3+ sans sous-classement.

extension UIButton {
  func setBackgroundColor(_ color: UIColor, for state: UIControlState) {
    let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
    UIGraphicsBeginImageContext(rect.size)
    color.setFill()
    UIRectFill(rect)
    let colorImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    setBackgroundImage(colorImage, for: state)
  }
}

avec cette extension, il est facile de gérer les couleurs pour différents états et il se décolorera votre couleur normale automatiquement au cas où la couleur mise en évidence n'est pas fournie.

button.setBackgroundColor(.red, for: .normal)
6
répondu Timur Bernikowich 2017-06-02 09:49:14

mise à jour:

utilisez la UIButtonBackgroundColor bibliothèque Swift.

OLD:

utilisez les helpers ci-dessous pour créer une image 1 px x 1 px avec une couleur de remplissage en échelle de gris:

UIImage *image = ACUTilingImageGray(248/255.0, 1);

ou une couleur de remplissage RVB:

UIImage *image = ACUTilingImageRGB(253/255.0, 123/255.0, 43/255.0, 1);

ensuite, utilisez ce image pour régler l'image de fond du bouton:

[button setBackgroundImage:image forState:UIControlStateNormal];

Helpers

#pragma mark - Helpers

UIImage *ACUTilingImageGray(CGFloat gray, CGFloat alpha)
{
    return ACUTilingImage(alpha, ^(CGContextRef context) {
        CGContextSetGrayFillColor(context, gray, alpha);
    });
}

UIImage *ACUTilingImageRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
{
    return ACUTilingImage(alpha, ^(CGContextRef context) {
        CGContextSetRGBFillColor(context, red, green, blue, alpha);
    });
}

UIImage *ACUTilingImage(CGFloat alpha, void (^setFillColor)(CGContextRef context))
{
    CGRect rect = CGRectMake(0, 0, 0.5, 0.5);
    UIGraphicsBeginImageContextWithOptions(rect.size, alpha == 1, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    setFillColor(context);
    CGContextFillRect(context, rect);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

Note: ACU est le préfixe de classe de ma bibliothèque statique Cocoa Touch appelée Acani Utilities, où AC est pour Acani, et U pour Utilities.

4
répondu ma11hew28 2015-04-26 03:46:27

essayez ça !!!!

pour L'événement TouchedDown définit une couleur et pour le TouchUpInside définit l'autre.

- (IBAction)touchedDown:(id)sender {
    NSLog(@"Touched Down");
    btn1.backgroundColor=[UIColor redColor];
}

- (IBAction)touchUpInside:(id)sender {
    NSLog(@"TouchUpInside");
    btn1.backgroundColor=[UIColor whiteColor];    
}
4
répondu Karan Alangat 2015-08-06 05:22:45

sous-classe L'UIButton et ajouter des propriétés inspectables pour une utilisation Commode (écrit dans Swift 3.0):

final class SelectableBackgroundButton: UIButton {

    private struct Constants {
        static let animationDuration: NSTimeInterval = 0.1
    }

    @IBInspectable
    var animatedColorChange: Bool = true

    @IBInspectable
    var selectedBgColor: UIColor = UIColor.blackColor().colorWithAlphaComponent(0.2)

    @IBInspectable
    var normalBgColor: UIColor = UIColor.clearColor()

    override var selected: Bool {
        didSet {
            if animatedColorChange {
                UIView.animateWithDuration(Constants.animationDuration) {
                    self.backgroundColor = self.selected ? self.selectedBgColor : self.normalBgColor
                }
            } else {
                self.backgroundColor = selected ? selectedBgColor : normalBgColor
            }
        }
    }

    override var highlighted: Bool {
        didSet {
            if animatedColorChange {
                UIView.animateWithDuration(Constants.animationDuration) {
                    self.backgroundColor = self.highlighted ? self.selectedBgColor : self.normalBgColor
                }
            } else {
                self.backgroundColor = highlighted ? selectedBgColor : normalBgColor
            }
        }
    }
}
4
répondu Bence Pattogato 2016-11-24 09:02:25

essayez ceci si vous avez une image:

-(void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;

ou voyez si showsTouchWhenHighlighted vous suffit.

2
répondu Siby 2014-11-19 04:00:10

vous pouvez classer L'UIButton et faire une belle forState.

colourButton.h

#import <UIKit/UIKit.h>

@interface colourButton : UIButton

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

@end

colourButton.m

#import "colourButton.h"

@implementation colourButton
{
    NSMutableDictionary *colours;
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    // If colours does not exist
    if(!colours)
    {
        colours = [NSMutableDictionary new];  // The dictionary is used to store the colour, the key is a text version of the ENUM
        colours[[NSString stringWithFormat:@"%lu", UIControlStateNormal]] = (UIColor*)self.backgroundColor;  // Store the original background colour
    }

    return self;
}

-(void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state
{
    // If it is normal then set the standard background here
    if(state & UIControlStateNormal)
    {
        [super setBackgroundColor:backgroundColor];
    }

    // Store the background colour for that state
    colours[[NSString stringWithFormat:@"%lu", state]]= backgroundColor;
}

-(void)setHighlighted:(BOOL)highlighted
{
    // Do original Highlight
    [super setHighlighted:highlighted];

    // Highlight with new colour OR replace with orignial
    if (highlighted && colours[[NSString stringWithFormat:@"%lu", UIControlStateHighlighted]])
    {
        self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateHighlighted]];
    }
    else
    {
        self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateNormal]];
    }
}

-(void)setSelected:(BOOL)selected
{
    // Do original Selected
    [super setSelected:selected];

    // Select with new colour OR replace with orignial
    if (selected && colours[[NSString stringWithFormat:@"%lu", UIControlStateSelected]])
    {
        self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateSelected]];
    }
    else
    {
        self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateNormal]];
    }
}

@end

Notes (C'est un exemple, je sais qu'il y a des problèmes et voici quelques-uns)

j'ai utilisé un Nsmutabldictionay pour stocker L'UIColor pour chaque État, je dois faire une conversion de texte désagréable pour la clé comme L'UIControlState n'est pas une belle ligne droite Int. Si c'est là que vous pouvez insérer un tableau avec autant d'objets et utiliser l'État comme un index.

pour cette raison, vous avez beaucoup de difficultés avec par exemple un bouton sélectionné et désactivé, un peu plus de logique est nécessaire.

un Autre problème est que si vous essayez de définir plusieurs couleurs en même temps, je n'ai pas essayé avec un bouton, mais si vous pouvez faire cela, il peut ne pas fonctionner

 [btn setBackgroundColor:colour forState:UIControlStateSelected & UIControlStateHighlighted];

j'ai supposé que c'est StoryBoard, il n'y a pas init, initWithFrame donc les ajouter si vous en avez besoin.

2
répondu Recycled Steel 2014-12-18 14:07:08

j'ai une sous-classe UIButton à source ouverte, STAButton , pour combler ce trou de fonctionnalité Béant. Disponible sous licence MIT. Fonctionne pour iOS 7+ (Je n'ai pas testé avec les versions iOS plus anciennes).

2
répondu Stunner 2015-05-27 00:27:27

pour résoudre ce problème j'ai créé une catégorie pour gérer les États backgroundColor avec UIButtons :

ButtonBackgroundColor-iOS

vous pouvez installer la catégorie comme un pod .

facile à utiliser avec objectif-c

@property (nonatomic, strong) UIButton *myButton;

...

[self.myButton bbc_backgroundColorNormal:[UIColor redColor]
                 backgroundColorSelected:[UIColor blueColor]];

encore plus facile à utiliser avec Swift :

import ButtonBackgroundColor

...

let myButton:UIButton = UIButton(type:.Custom)

myButton.bbc_backgroundColorNormal(UIColor.redColor(), backgroundColorSelected: UIColor.blueColor())

je vous recommande d'importer la gousse avec:

platform :ios, '8.0'
use_frameworks!

pod 'ButtonBackgroundColor', '~> 1.0'

en utilisant use_frameworks! dans votre Podfile rend plus facile d'utiliser vos gousses avec Swift et objectif-C.

IMPORTANT

j'ai aussi écrit un billet de Blog avec plus d'informations.

2
répondu Gabriel.Massana 2016-02-09 21:37:16

Essayer tintColor :

_button.tintColor = [UIColor redColor];
1
répondu jjv360 2013-01-25 14:06:28

voici le code dans Swift pour sélectionner l'état du bouton:

func imageWithColor(color:UIColor) -> UIImage {
    let rect:CGRect = CGRectMake(0.0, 0.0, 1.0, 1.0)
     UIGraphicsBeginImageContext(rect.size)
    let context:CGContextRef = UIGraphicsGetCurrentContext()!
    CGContextSetFillColorWithColor(context, color.CGColor)
    CGContextFillRect(context, rect)
    let image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
    return image;
}

exemple:

    self.button.setImage(self.imageWithColor(UIColor.blackColor()), forState: .Highlighted)
1
répondu Mike Zriel 2016-01-06 07:56:51

Drop et vous êtes bon pour aller:

* proerty peut être défini dans IB, et si aucun fond en surbrillance n'est défini, le fond ne changera pas lorsqu'on appuie sur

private var highlightedBackgroundColors = [UIButton:UIColor]()
private var unhighlightedBackgroundColors = [UIButton:UIColor]()
extension UIButton {

    @IBInspectable var highlightedBackgroundColor: UIColor? {
        get {
            return highlightedBackgroundColors[self]
        }

        set {
            highlightedBackgroundColors[self] = newValue
        }
    }

    override open var backgroundColor: UIColor? {
        get {
            return super.backgroundColor
        }

        set {
            unhighlightedBackgroundColors[self] = newValue
            super.backgroundColor = newValue
        }
    }

    override open var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }

        set {
            if highlightedBackgroundColor != nil {
                super.backgroundColor = newValue ? highlightedBackgroundColor : unhighlightedBackgroundColors[self]
            }
            super.isHighlighted = newValue
        }
    }
}
1
répondu shoe 2017-02-01 09:00:05

au-dessous de UIIImage l'extension générera l'objet image avec le paramètre de couleur spécifié.

extension UIImage {
    static func imageWithColor(tintColor: UIColor) -> UIImage {
        let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        tintColor.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
       }
    }

un exemple d'usage pour un bouton peut être appliqué pour l'objet bouton comme:

setupButton.setBackgroundImage(UIImage.imageWithColor(tintColor: UIColor(displayP3Red: 232/255, green: 130/255, blue: 121/255, alpha: 1.0)), for: UIControlState.highlighted)

setupButton.setBackgroundImage(UIImage.imageWithColor(tintColor: UIColor(displayP3Red: 255/255, green: 194/255, blue: 190/255, alpha: 1.0)), for: UIControlState.normal)
1
répondu manoj kumar 2018-04-17 11:01:09
class CustomButton: UIButton {

    override var isHighlighted: Bool {
        didSet {
            if (isHighlighted) {
                alpha = 0.5
            }
            else {
                alpha = 1
            }            
        }
    }

}
1
répondu evya 2018-06-28 10:13:48

utiliser https://github.com/swordray/UIButtonSetBackgroundColorForState

ajouter à Podfile en utilisant CocoaPods

pod "UIButtonSetBackgroundColorForState"

Swift

button.setBackgroundColor(.red, forState: .highlighted)

Objectif-C

[button setBackgroundColor:[UIColor redColor] forState:UIControlStateHighlighted];
1
répondu swordray 2018-09-03 18:09:29

si vous n'annulez pas il suffit de mettre deux actions touchdown touchUpInside

0
répondu Roman Bambura 2016-12-28 10:35:03

Swift 3:

extension UIButton {
    private func imageWithColor(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, forUIControlState state: UIControlState) {
        self.setBackgroundImage(imageWithColor(color: color), for: state)
    }
}
0
répondu Elita 2017-04-25 12:14:53

il est possible de le régler par XIB. Dans XIB mettre mis en évidence la couleur de teinte comme le désir u tout en appuyant sur le bouton. Comme il n'y a pas d'approche programmatique juste pour cela jusqu'à présent. Donc c'est facile pour vous en le mettant en XIB .

, Il fonctionne très bien :) enjoy..

-4
répondu Shashank shree 2013-01-25 15:39:51