¿Cómo cambiar el color de fondo de un UIButton mientras está resaltado?

En algún momento de mi aplicación tengo un UIButton resaltado (por ejemplo, cuando un usuario tiene el dedo sobre el botón) y necesito cambiar el color de fondo mientras el botón está resaltado (de modo que mientras el dedo del usuario aún está en el botón) )

Intenté lo siguiente:

 _button.backgroundColor = [UIColor redColor]; 

Pero no está funcionando. El color sigue siendo el mismo Intenté el mismo código cuando el botón no está resaltado y funciona bien. También intenté llamar a -setNeedsDisplay después de cambiar el color, no tuvo ningún efecto.

¿Cómo forzar el botón para cambiar el color de fondo?

Puede anular el método setHighlighted .

C objective

 - (void)setHighlighted:(BOOL)highlighted { [super setHighlighted:highlighted]; if (highlighted) { self.backgroundColor = UIColorFromRGB(0x387038); } else { self.backgroundColor = UIColorFromRGB(0x5bb75b); } } 

Swift 3.0 y Swift 4.1

 override open var isHighlighted: Bool { didSet { backgroundColor = isHighlighted ? UIColor.black : UIColor.white } } 

No estoy seguro de si este tipo de solución resuelve lo que está buscando, o se ajusta a su outlook general de desarrollo, pero lo primero que intentaría sería cambiar el color de fondo del botón en el evento touchdown.

Opción 1:

Necesitará dos eventos para capturar, UIControlEventTouchDown sería para cuando el usuario presiona el botón. UIControlEventTouchUpInside y UIControlEventTouchUpOutside serán para cuando suelten el botón para devolverlo al estado 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]; 

Opcion 2:

Devuelve una imagen hecha con el color de resaltado que quieras. Esto también podría ser una categoría.

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

y luego cambie el estado resaltado del botón:

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

No es necesario anular la propiedad highlighted como calculada. Puede usar el observador de propiedades para activar el cambio de color de fondo:

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

Swift 4

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

Rápidamente puede anular el descriptor de acceso de la propiedad resaltada (o seleccionada) en lugar de anular el método setHighlighted

 override var highlighted: Bool { get { return super.highlighted } set { if newValue { backgroundColor = UIColor.blackColor() } else { backgroundColor = UIColor.whiteColor() } super.highlighted = newValue } } 

Una práctica extensión genérica en 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) } } 

Anular la variable resaltada. Agregar @IBInspectable te hace editar el backgroundColor resaltado en el guión gráfico, que también es ingenioso.

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

una solución más compacta (basada en la respuesta de @ aleksejs-mjaliks ):

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

Extensión UIButton con syntax 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) }} 

Úselo como:

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

Respuesta original: https://stackoverflow.com/a/30604658/3659227

Puede usar esta categoría que agrega el método setBackgroundColor: forState:

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

Aquí hay un enfoque en Swift, usando una extensión UIButton para agregar un IBInspectable, llamado destacadoBackgroundColor. Similar a la subclasificación, sin requerir una subclase.

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

Espero que esto ayude.

Mi mejor solución para Swift 3+ sin subclases.

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

Con esta extensión, es fácil administrar colores para diferentes estados y se desvanecerá automáticamente su color normal en caso de que no se proporcione el color resaltado.

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

ACTUALIZAR:

Use la biblioteca UIButtonBackgroundColor Swift.

ANTIGUO:

Utilice los ayudantes siguientes para crear una imagen de 1 px x 1 px con un color de relleno en escala de grises:

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

o un color de relleno RGB:

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

Luego, usa esa image para establecer la imagen de fondo del botón:

 [button setBackgroundImage:image forState:UIControlStateNormal]; 

Ayudantes

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

Nota: ACU es el prefijo de clase de mi Biblioteca Estática Cocoa Touch llamada Acani Utilities, donde AC es para Acani y U para Utilidades.

Prueba esto !!!!

Para el conjunto de eventos TouchedDown Un color y para TouchUpInside establecen el otro.

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

Subclase el UIButton y agregue propiedades inspeccionables para un uso conveniente (escrito 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 } } } } 

Intenta esto si tienes una imagen:

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

o vea si showsTouchWhenHighlighted es suficiente para usted.

Puede subclasificar el UIButton y hacer un buen forState.

colourButton.h

 #import  @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 

Notas (Este es un ejemplo, sé que hay problemas y aquí hay algunos)

He usado un NSMutableDictionay para almacenar el UIColor para cada estado, tengo que hacer una desagradable conversión de texto para la clave ya que el UIControlState no es un buen intline directo. Si fuera donde podría iniciar una matriz con tantos objetos y usar el estado como índice.

Debido a esto, muchos tienen dificultades con, por ejemplo, un botón seleccionado y deshabilitado, se necesita algo más de lógica.

Otro problema es si intentas configurar varios colores al mismo tiempo, no lo he intentado con un botón, pero si puedes hacerlo, puede que no funcione

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

He supuesto que esto es StoryBoard, no hay init, initWithFrame, así que agrégalos si los necesitas.

Tengo una subclase UIButton de código abierto, STAButton , para completar este agujero de funcionalidad abierta. Disponible bajo la licencia de MIT. Funciona para iOS 7+ (no lo he probado con versiones anteriores de iOS).

Para resolver este problema creé una Categoría para manejar backgroundColor States con UIButtons :
ButtonBackgroundColor-iOS

Puede instalar la categoría como un pod .

Fácil de usar con Objective-C

 @property (nonatomic, strong) UIButton *myButton; ... [self.myButton bbc_backgroundColorNormal:[UIColor redColor] backgroundColorSelected:[UIColor blueColor]]; 

Aún más fácil de usar con Swift :

 import ButtonBackgroundColor ... let myButton:UIButton = UIButton(type:.Custom) myButton.bbc_backgroundColorNormal(UIColor.redColor(), backgroundColorSelected: UIColor.blueColor()) 

Te recomiendo que importes el pod con:

 platform :ios, '8.0' use_frameworks! pod 'ButtonBackgroundColor', '~> 1.0' 

Usando use_frameworks! en tu archivo Podfile es más fácil usar tus pods con Swift y objective-C.

IMPORTANTE

También escribí una publicación de blog con más información.

Pruebe tintColor :

 _button.tintColor = [UIColor redColor]; 

Aquí está el código en Swift para seleccionar el estado del botón:

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

Ejemplo:

  self.button.setImage(self.imageWithColor(UIColor.blackColor()), forState: .Highlighted) 

Súbalo y estás listo para ir:
* la libertad se puede configurar en IB, y si no se establece ningún fondo resaltado, el fondo no cambiará cuando se presione

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

Debajo de la extensión UIIImage se generará un objeto de imagen con el parámetro de color especificado.

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

Se puede aplicar un uso de ejemplo para un botón para el objeto de botón como:

 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) 
 class CustomButton: UIButton { override var isHighlighted: Bool { didSet { if (isHighlighted) { alpha = 0.5 } else { alpha = 1 } } } } 

si no lo anulas, simplemente establece dos acciones touchDown touchUpInside

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

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

Agregar a Podfile usando CocoaPods

 pod "UIButtonSetBackgroundColorForState" 

Rápido

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

C objective

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

Es posible establecerlo a través de XIB. En xib establece el color del tinte resaltado como desees mientras tocas el botón. Como no hay un enfoque programáticamente correcto para esto hasta ahora. Por lo tanto, es fácil para usted establecerlo en XIB.

Funcionará bien 🙂 disfruta …