[ios] Come cambiare il colore di sfondo di un UIButton mentre è evidenziato?


12 Answers

Non sono sicuro che questo tipo di soluzione risolva ciò che cerchi, oppure si adatta al tuo panorama generale di sviluppo, ma la prima cosa che proverei sarebbe cambiare il colore di sfondo del pulsante sull'evento touchDown.

Opzione 1:

Avresti bisogno di due eventi da catturare, UIControlEventTouchDown sarebbe per quando l'utente preme il pulsante. UIControlEventTouchUpInside e UIControlEventTouchUpOutside saranno per quando rilasciano il pulsante per riportarlo allo stato normale

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

Opzione 2:

Restituisce un'immagine creata dal colore di evidenziazione desiderato. Questa potrebbe anche essere una categoria.

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

e quindi modificare lo stato evidenziato del pulsante:

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

Ad un certo punto nella mia app ho un UIButton evidenziato (ad esempio quando un utente ha il dito sul pulsante) e ho bisogno di cambiare il colore di sfondo mentre il pulsante è evidenziato (così mentre il dito dell'utente è ancora sul pulsante ).

Ho provato il seguente:

_button.backgroundColor = [UIColor redColor];

Ma non sta funzionando. Il colore rimane lo stesso Ho provato lo stesso pezzo di codice quando il pulsante non è evidenziato e funziona bene. Ho anche provato a chiamare -setNeedsDisplay dopo aver cambiato il colore, non ha avuto alcun effetto.

Come forzare il pulsante per cambiare il colore di sfondo?




Rilascialo e sei a posto:
* la proerty può essere impostata in IB, e se non è impostato uno sfondo evidenziato, lo sfondo non cambierà se premuto

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



Sostituisci la variabile evidenziata. Aggiungendo @IBInspectable puoi modificare lo sfondo evidenziatoColore nello storyboard, che è anche elegante.

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



Ecco un approccio in Swift, usando un'estensione UIButton per aggiungere un IBInspectable, chiamato evidenziatoBackgroundColor. Simile alla sottoclasse, senza richiedere una sottoclasse.

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

Spero che aiuti.




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



AGGIORNARE:

Usa la libreria UIButtonBackgroundColor Swift.

VECCHIO:

Utilizza gli helper in basso per creare un'immagine di 1 px x 1 px con un colore di riempimento in scala di grigi:

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

o un colore di riempimento RGB:

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

Quindi, usa image per impostare l'immagine di sfondo del pulsante:

[button setBackgroundImage:image forState:UIControlStateNormal];

Helpers

#pragma mark - Helpers

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

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

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

Nota: ACU è il prefisso di classe della mia libreria Cocoa Touch Static denominata Acani Utilities, dove AC è per Acani e U è per utilità.




Sottoclassi UIButton e aggiungi proprietà ispezionabili per un uso conveniente (scritto in 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
            }
        }
    }
}



Puoi creare una sottoclasse di UIButton e creare un bello perStato.

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

Note (Questo è un esempio, so che ci sono problemi e qui ce ne sono alcuni)

Ho usato un NSMutableDictionay per archiviare l'UIColor per ogni stato, devo fare una brutta conversione del testo per il Key in quanto l'UIControlState non è un bel dritto. Int. Se fosse dove potresti iniziare una matrice con tanti oggetti e usare lo stato come indice.

Per questo motivo molti hanno difficoltà ad es. Con un pulsante selezionato e disabilitato, è necessaria una maggiore logica.

Un altro problema è che se provi a impostare più colori contemporaneamente, non ho provato con un pulsante, ma se riesci a farlo potrebbe non funzionare

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

Ho pensato che fosse StoryBoard, non ci sono init, initWithFrame quindi aggiungili se ne hai bisogno.




Ecco il codice in Swift per selezionare lo stato del pulsante:

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

Esempio:

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



Per risolvere questo problema ho creato una categoria per gestire backgroundColor States con UIButtons :
ButtonBackgroundColor-iOS

Puoi installare la categoria come pod .

Facile da usare con Objective-C

@property (nonatomic, strong) UIButton *myButton;

...

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

Ancora più facile da usare con Swift :

import ButtonBackgroundColor

...

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

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

Ti consiglio di importare il pod con:

platform :ios, '8.0'
use_frameworks!

pod 'ButtonBackgroundColor', '~> 1.0'

Usando use_frameworks! nel tuo Podfile rende più facile usare i tuoi pod con Swift e C-obiettivo.

IMPORTANTE

somethingaboutios.wordpress.com/2016/02/09/…




In rapido è possibile sovrascrivere l'accessor della proprietà evidenziata (o selezionata) anziché ignorare il metodo setHighlighted

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



È possibile impostarlo tramite XIB. In xib imposta il colore Tinta evidenziata come desideri mentre premi il pulsante. Dal momento che non esiste un approccio al punto giusto da un punto di vista programmatico. Quindi è facile per te impostandolo in XIB.

Funzionerà benissimo :) divertiti ..




Estensione UIButton con sintassi 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)
    }}

Usalo come:

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

Risposta originale: https://.com/a/30604658/3659227




Related