web-dev-qa-db-fra.com

Comment changer la couleur de fond d'un bouton UIB lorsqu'il est en surbrillance?

À un moment donné dans mon application, j'ai un UIButton en surbrillance (par exemple lorsqu'un utilisateur a le doigt sur le bouton) et je dois changer la couleur d'arrière-plan lorsque le bouton est en surbrillance (ainsi lorsque le doigt de l'utilisateur est toujours sur le bouton).

J'ai essayé ce qui suit:

_button.backgroundColor = [UIColor redColor];

Mais ça ne fonctionne pas. La couleur reste la même. J'ai essayé le même morceau de code lorsque le bouton n'est pas en surbrillance et cela fonctionne bien. J'ai aussi essayé d'appeler -setNeedsDisplay après avoir changé la couleur, cela n'a eu aucun effet.

Comment forcer le bouton pour changer la couleur de fond?

223
MartinMoizard

Vous pouvez remplacer la méthode UIButtonsetHighlighted.

Objective-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
    }
}
391
Thomas Decaux

Je ne sais pas si cela résout ce que vous recherchez, ou si cela correspond à votre paysage de développement général, mais la première chose que j'essaierais serait de changer la couleur d'arrière-plan du bouton de l'événement TouchDown.

Option 1:

Vous aurez besoin de deux événements à capturer, UIControlEventTouchDown le sera lorsque l'utilisateur appuiera sur le bouton. UIControlEventTouchUpInside et UIControlEventTouchUpOutside seront pour quand ils relâcheront le bouton pour le ramener à 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:

Renvoie une image créée à partir de la couleur de surbrillance souhaitée. 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;
}

puis changez l’état du bouton en surbrillance:

[myButton setBackgroundImage:[self imageWithColor:[UIColor greenColor]] forState:UIControlStateHighlighted];
297
Tim

Il n'est pas nécessaire de remplacer highlighted en tant que propriété calculée. Vous pouvez utiliser Property Observer pour déclencher le changement de couleur d'arrière-plan:

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

Swift 4

override open var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white
    }
}
92
Aleksejs Mjaliks

Dans Swift, vous pouvez remplacer l'accesseur de la propriété en surbrillance (ou sélectionnée) au lieu de remplacer 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
        }
    }
45
Jake Hall

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.

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)
    }
}
44
Giordano Scalzo

Ignorer la variable en surbrillance. L'ajout de @IBInspectable vous permet de modifier la couleur d'arrière-plan surlignée dans le storyboard, ce qui est très pratique également.

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
        }
    }
}
23
mash

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

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()
    }
}

Si vous ne souhaitez pas remplacer, il s'agit d'une version mise à jour de la réponse de @ timur-bernikowich (Swift 4.2):

extension UIButton {
  func setBackgroundColor(_ color: UIColor, forState controlState: UIControl.State) {
    let colorImage = UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { _ in
      color.setFill()
      UIBezierPath(rect: CGRect(x: 0, y: 0, width: 1, height: 1)).fill()
    }
    setBackgroundImage(colorImage, for: controlState)
  }
}
17
Federico Zanetello

Extension UIButton avec la syntaxe Swift 3 + :

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)
    }}

Utilisez-le comme:

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

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

12
Maverick

Voici une approche dans Swift, qui utilise une extension UIButton pour ajouter un élément IBInspectable, appelé highlightBackgroundColor. Similaire au sous-classement, sans nécessiter 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 ça aide.

10
Fostah

Vous pouvez utiliser cette catégorie pour ajouter la méthode setBackgroundColor: forState:

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

9
Damien Romito

Ma meilleure solution pour 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 elle se décolore automatiquement si la couleur en surbrillance n'est pas fournie.

button.setBackgroundColor(.red, for: .normal)
7

Sous-classe UIButton et ajoutez des propriétés inspectables pour une utilisation pratique (écrit en 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
Bence Pattogato

Essaye ça !!!!

Pour l'événement TouchedDown, définissez une couleur et pour TouchUpInside, définissez l'autre.

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

- (IBAction)touchUpInside:(id)sender {
    NSLog(@"TouchUpInside");
    btn1.backgroundColor=[UIColor whiteColor];    
}
4
Karan Alangat

MISE À JOUR:

Utilisez la bibliothèque IButtonBackgroundColor Swift.

VIEUX:

Utilisez les aides ci-dessous pour créer une image de 1 px x 1 px avec une couleur de remplissage en niveaux 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 cette image pour définir l’image d’arrière-plan du bouton:

[button setBackgroundImage:image forState:UIControlStateNormal];

Aides

#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;
}

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

4
ma11hew28

Sur le scénarimage ...

Vous pouvez modifier les paramètres pour chaque état UIButton. Par exemple, sélectionnez "Sélectionné" et vous pourrez ensuite changer la couleur du texte pour cet état.

Pour changer l’arrière-plan lorsque UIButton est en surbrillance:

  1. Sélectionnez le bouton souhaité dans Storyboard.
  2. Sélectionnez la configuration d'état souhaitée. Pour votre cas, sélectionnez "En surbrillance". How to change the state configuration in Storyboard.
  3. Changer la couleur de fond. Vous pouvez maintenant naviguer vers d'autres états à l'aide de l'étape 2 et spécifier la couleur d'arrière-plan pour cet état. How to change the background color in Storyboard.
2
Josh Wolff

Vous pouvez sous-classer le UIButton et faire un Nice 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 (Ceci est un exemple, je sais qu'il y a des problèmes et en voici quelques uns)

J'ai utilisé un NSMutableDictionay pour stocker UIColor pour chaque état. Je dois effectuer une conversion de texte désagréable pour la clé, car UIControlState n'est pas un Nice straight Int. Si c'est le cas, vous pouvez initier un tableau contenant autant d'objets et utiliser l'état en tant qu'index.

Pour cette raison, vous avez souvent des 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 le faire, cela risque de ne pas fonctionner.

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

J'ai supposé que c'était StoryBoard, il n'y a pas d'init, initWithFrame, donc ajoutez-les si vous en avez besoin.

2
Recycled Steel

J'ai open-source une sous-classe UIButton, STAButton , pour combler ce trou de fonctionnalité. Disponible sous la licence MIT. Fonctionne pour iOS 7+ (je n'ai pas testé avec les anciennes versions iOS).

2
Stunner
class CustomButton: UIButton {

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

}
2
evya

Pour résoudre ce problème, j'ai créé une catégorie permettant de gérer backgroundColor États avec UIButtons:
ButtonBackgroundColor-iOS

Vous pouvez installer la catégorie en tant que pod .

Facile à utiliser avec Objective-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 le pod avec:

platform :ios, '8.0'
use_frameworks!

pod 'ButtonBackgroundColor', '~> 1.0'

Utilisation de use_frameworks! dans votre podfile, il est plus facile d’utiliser vos pods avec Swift et objective-C.

IMPORTANT

J'ai aussi écrit un article de blog avec plus d'informations.

2
Gabriel.Massana

Essayez ceci si vous avez une image:

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

ou voyez si showsTouchWhenHighlighted vous suffit.

2
Siby

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

Ajouter à Podfile en utilisant CocoaPods

pod "UIButtonSetBackgroundColorForState"

Rapide

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

Objective-C

[button setBackgroundColor:[UIColor redColor] forState:UIControlStateHighlighted];
2
swordray


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
shoe

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
Mike Zriel

En dessous de UIIImage l'extension générera un 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'utilisation d'un bouton peut être appliqué à l'objet bouton comme suit:

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
manoj kumar

Essayez tintColor:

_button.tintColor = [UIColor redColor];
1
jjv360

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
Elita

si vous ne remplacez pas, définissez deux actions touchDown touchUpInside

0
Roman Bambura