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


236

En algún momento de mi aplicación, tengo un resaltado UIButton(por ejemplo, cuando un usuario tiene el dedo en el botón) y necesito cambiar el color de fondo mientras el botón está resaltado (por lo tanto, mientras el dedo del usuario todavía 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 -setNeedsDisplaydespués de cambiar el color, no tuvo ningún efecto.

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


Respuestas:


411

Puedes anular UIButtonel setHighlightedmétodo.

C objetivo

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

Si. Es una buena forma de hacer esto. Porque puedes definir varios botones similares.
Paul Brewczynski

3
Solo una pregunta para novatos, ¿dónde subclasificarías ese método de botón? Si tengo un botón en un controlador de vista llamado ConversionViewController, ¿cómo configuraría el botón para cambiar el color de fondo cuando esté resaltado o pulsado? ¿Subclase el setHIghlighted en COnversionViewController?
Beanno1116

Entonces, hay un problema con esta respuesta que encontré. Si desea que el mismo color esté disponible cuando seleccione el Botón, se llamará a setHighlighted después de setSelected y, por lo tanto, anulará cualquier estilo seleccionado que tenga. La solución anterior podría ser mejor si desea seleccionar el botón también
HaloZero

3
@YakivKovalskiy suponiendo que está utilizando una subclase, puede agregar dos propiedades UIColor, por ejemplo, normalBackground y resaltadoBackground, luego asignar self.backgroundColor = normalBackground o resaltadoBackground en consecuencia. No olvide agregar un método init para facilitar su uso, por ejemplo initWithBackground: resaltadoBackground:
SK.

2
Buena solución, solo una sugerencia:backgroundColor = isHighlighted ? .lightGray : .white
Fantini

298

No estoy seguro de si esto resuelve lo que buscas o si se ajusta a tu panorama 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ía 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:

Devuelva una imagen hecha del color de resaltado que desee. 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];

3
Agregue UIControlEventTouchUpOutside y UIControlEventTouchCancel a buttonHighlight: lista de eventos y funcionará siempre.
Evgen Bodunov

La opción dos es la mejor que he encontrado hasta ahora. Sin embargo, supongo que los guiones gráficos tienen sus ventajas en este caso.
Jack Solomon

La respuesta de Thomas es mejor y eso es lo que yo también uso
Van Du Tran

26
Si está utilizando layer.cornerRadiusy opta por la opción n. ° 2, deberá asegurarse de establecerlo clipsToBoundsen verdadero para redondear también las esquinas de la imagen.
Sky

3
Si alguien se detiene y necesita una respuesta en Swift: stackoverflow.com/questions/26600980/…
invierno el

94

No es necesario anular highlightedcomo propiedad 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 open var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white
    }
}

1
Nunca he usado funcionalidades como esta. ¿Puedes explicar a dónde va esto? ¿Está en la función del botón IBActionPress o en viewDidLoad?
Dave G

¿Qué sucede si tengo múltiples botones UIB con diferentes colores?
Slavcho

66
@Dave G, puede crear una nueva subclase de UIButton haciendo clic File>New>File>Cocoa Touch Classy configurándola en subclass of UIButton. Nombre el archivo para ex CustomButton, que se convertirá en el nombre del archivo y el nombre de la clase. Dentro de este archivo, coloque el override var highlightedcódigo que se muestra arriba. Último paso, configure el UIButton en Interface Builder para usar esta CustomButtonsubclase yendo a la página de Propiedades donde dice "Clase personalizada" y tiene un cuadro desplegable. Dirá "UIButton" en letras grises. La lista desplegable debe mostrar CustomButton. Seleccione esto, y el botón ahora está subclasificado.
James Toomey

¡Por qué nadie mencionó que se llama al configurador solo cuando toca el botón, pero no durante el diseño inicial! Entonces, por defecto, no hay color hasta que tocas el botón.
Dmitrii

Entonces, para que funcione, también debe llamar explícitamente a isHighlighted = falsealgún lugar al principio (por ejemplo, en la inicialización).
Dmitrii

50

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

45

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

Esto funciona totalmente, pero estoy confundido ¿cómo pudiste resolver esto? Los parámetros no están en la documentación o UIButton.h por lo que puedo decir.
shimizu

1
Esta es la sintaxis rápida que emula el comportamiento de anular setHightlighted en el objetivo c. Consulte la documentación sobre Propiedades calculadas aquí developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Jake Hall

11
En Swift puedes usar didSet
Dam

1
He agregado un ejemplo con el observador de propiedades: stackoverflow.com/a/29186375/195173 .
Aleksejs Mjaliks

Creo que lo que @shimizu preguntaba era cómo sabías que highlightedera una propiedad en UIButton. La respuesta es que es una propiedad en UIControl de la cual UIButton hereda.
Adam Johns

25

Anular variable resaltada. Agregar le @IBInspectablehace 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
        }
    }
}

20

Una solución más compacta (basada en la respuesta @ 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()
    }
}

Si no desea anular, esta es una versión actualizada de la respuesta 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)
  }
}

@FedericoZanetello esto anulará está resaltado en todos los botones de su aplicación, lo cual no es una buena solución en mi opinión. Iré con la respuesta de Timur.
Usama bin Attique

13

Extensión UIButton con sintaxis 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


10

Aquí hay un enfoque en Swift, usando una extensión UIButton para agregar un IBInspectable, llamado resaltadoBackgroundColor. Similar a la subclase, 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.


1
Para swift 2.0, deberá actualizar la llamada a objc_setAssociatedObject para usar una enumeración: objc_setAssociatedObject (self, & NormalBackgroundColorKey, newValue, .OBJC_ASSOCIATION_RETAIN)
Eli Burke

Definitivamente la mejor manera en Swift si quieres mantenerlo todo en Storyboard.
davidethell

1
Prefiero usar la subclase, no la extensión, ya que esto afectará a toda la aplicación
Hossam Ghareeb


9

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 los colores para diferentes estados y se desvanecerá su color normal automáticamente en caso de que no se proporcione el color resaltado.

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

4

ACTUALIZAR:

Use la biblioteca UIButtonBackgroundColor Swift.

ANTIGUO:

Utilice los siguientes ayudantes 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, use eso imagepara configurar 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: ACUes el prefijo de clase de mi biblioteca estática Cocoa Touch llamada Acani Utilities, donde AC es para Acani y U es para Utilities.


4

Prueba esto !!!!

Para TouchedDown Event, configure un color y para TouchUpInside configure el otro.

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

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

2
Trabajó para mi. Solo tuve que agregar - (IBAction)onButtonTouchDragOutside:(UIButton *)sender {para asegurarme de que el color no permanezca encendido cuando el usuario accidentalmente arrastra su dedo del botón.
SudoPlz

4

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

3

Puedes subclasificar el UIButton y hacer un buen 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

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 conversión de texto desagradable para la clave ya que el UIControlState no es un buen int. Si pudiera iniciar una matriz con tantos objetos y usar el estado como índice.

Debido a esto, puede tener dificultades con, por ejemplo, un botón seleccionado y deshabilitado, se necesita más lógica.

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

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

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


3
extension UIButton {
    func setBackgroundColor(color: UIColor, forState: UIControl.State) {
        let size = CGSize(width: 1, height: 1)
        UIGraphicsBeginImageContext(size)
        let context = UIGraphicsGetCurrentContext()
        context?.setFillColor(color.cgColor)
        context?.fill(CGRect(origin: CGPoint.zero, size: size))
        let colorImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        setBackgroundImage(colorImage, for: forState)
    }

}

Swift 5 , gracias @Maverick


3

Detalles

  • Xcode 11.1 (11A1027), Swift 5

Solución

import UIKit

extension UIColor {
    func createOnePixelImage() -> UIImage? {
        let size = CGSize(width: 1, height: 1)
        UIGraphicsBeginImageContext(size)
        defer { UIGraphicsEndImageContext() }
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.setFillColor(cgColor)
        context.fill(CGRect(origin: .zero, size: size))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

extension UIButton {
    func setBackground(_ color: UIColor, for state: UIControl.State) {
        setBackgroundImage(color.createOnePixelImage(), for: state)
    }
}

Uso

button.setBackground(.green, for: .normal)

2

Prueba esto si tienes una imagen:

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

o ver si showsTouchWhenHighlightedes suficiente para ti.


Traté de jugar con showsTouchWhenHighlighted pero no me ayudó. No quiero usar setBackgroundImage: forState :. De hecho, estaba tratando de usar backgroundColor para no usar ninguna imagen.
MartinMoizard

2

He abierto una subclase de UIButton , STAButton , para llenar este vacío de funcionalidad. Disponible bajo la licencia MIT. Funciona para iOS 7+ (no lo he probado con versiones anteriores de iOS).


2

Para resolver este problema, creé una categoría para manejar backgroundColorestados con UIButtons:
ButtonBackgroundColor-iOS

Puedes 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 importar el pod con:

platform :ios, '8.0'
use_frameworks!

pod 'ButtonBackgroundColor', '~> 1.0'

Usando use_frameworks! en su Podfile facilita el uso de sus pods con Swift y Objective-C.

IMPORTANTE

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


2
class CustomButton: UIButton {

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

}


1

Prueba tintColor:

_button.tintColor = [UIColor redColor];

¿Estás seguro de que está vinculado en IB? ¿Qué obtienes si lo haces NSLog(@"%@", _button);?
jjv360

1
Esto no funcionará si está utilizando a UIButtonTypeCustom.
JaredH

1

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)

1


Suéltelo y estará listo para comenzar : * la proeza se puede establecer en IB, y si no se establece un 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
        }
    }
}

1

La UIIImageextensión a continuación 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)

1

simple es usar esa extensión UIButton SOLAMENTE

extension UIButton {

    func setBackgroundColor(color: UIColor, forState: UIControl.State) {
        self.clipsToBounds = true  // add this to maintain corner radius
        UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
        if let context = UIGraphicsGetCurrentContext() {
            context.setFillColor(color.cgColor)
            context.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
            let colorImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            self.setBackgroundImage(colorImage, for: forState)
        }
    }

}

y usa esto

 optionButton.setBackgroundColor(color: UIColor(red:0.09, green:0.42, blue:0.82, alpha:1.0), forState: .selected)

 optionButton.setBackgroundColor(color: UIColor(red:0.96, green:0.96, blue:0.96, alpha:1.0), forState: .highlighted)

 optionButton.setBackgroundColor(color: UIColor(red:0.96, green:0.96, blue:0.96, alpha:1.0), forState: .normal)


0

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

en Swift 5

Para aquellos que no quieren usar un fondo de color para superar el estado seleccionado

Simplemente puede superar el problema utilizando la instrucción #Selector & if para cambiar fácilmente los colores UIButton para cada estado individualmente

Por ejemplo:

    override func viewDidLoad() {
    super.viewDidLoad()
    self.myButtonOutlet.backgroundColor = UIColor.white  //to reset the button color to its original color ( optionally )
}

@IBOutlet weak var myButtonOutlet: UIButton!{
    didSet{  // Button selector and image here
        self.myButtonOutlet.setImage(UIImage(systemName: ""), for: UIControl.State.normal)

        self.myButtonOutlet.setImage(UIImage(systemName: "checkmark"), for: UIControl.State.selected)



        self.myButtonOutlet.addTarget(self, action: #selector(tappedButton), for: UIControl.Event.touchUpInside)
    }
}

@objc func tappedButton() {  // Colors selection is here
    if self.myButtonOutlet.isSelected == true {

        self.myButtonOutlet.isSelected = false
        self.myButtonOutlet.backgroundColor = UIColor.white         
    } else {
        self.myButtonOutlet.isSelected = true

        self.myButtonOutlet.backgroundColor = UIColor.black
        self.myButtonOutlet.tintColor00 = UIColor.white

    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.