¿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?

MartinMoizard
fuente

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
    }
}
Thomas Decaux
fuente
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];
Tim
fuente
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
    }
}
Aleksejs Mjaliks
fuente
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)
    }
}
Giordano Scalzo
fuente
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
        }
    }
Jake Hall
fuente
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
        }
    }
}
mezcla
fuente
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)
  }
}
Federico Zanetello
fuente
@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

Disidente
fuente
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.

Fostah
fuente
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)
Timur Bernikovich
fuente
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.

ma11hew28
fuente
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];    
}
Karan Alangat
fuente
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
            }
        }
    }
}
Bence Pattogato
fuente
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.

Acero reciclado
fuente
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

dengST30
fuente
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)
Vasily Bodnarchuk
fuente
2

Prueba esto si tienes una imagen:

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

o ver si showsTouchWhenHighlightedes suficiente para ti.

Siby
fuente
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).

Persona maravillosa
fuente
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.

Gabriel.Massana
fuente
2
class CustomButton: UIButton {

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

}
evya
fuente
1

Prueba tintColor:

_button.tintColor = [UIColor redColor];
jjv360
fuente
¿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)
Mike Zriel
fuente
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
        }
    }
}
zapato
fuente
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)
Manoj Kumar
fuente
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)
Muhammad Ahmad
fuente
0

si no va a anular, simplemente configure dos acciones touchDown touchUpInside

Bambura romana
fuente
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)
    }
}
Elita
fuente
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

    }
}
Let.Simoo
fuente