Jak zmienić kolor tła przycisku UIB, gdy jest podświetlony?

236

W pewnym momencie mojej aplikacji mam wyróżnione UIButton(na przykład, gdy użytkownik trzyma palec na przycisku) i muszę zmienić kolor tła, gdy przycisk jest podświetlony (więc gdy palec użytkownika jest nadal na przycisku) .

Próbowałem następujące:

_button.backgroundColor = [UIColor redColor];

Ale to nie działa. Kolor pozostaje taki sam. Próbowałem tego samego kodu, gdy przycisk nie jest podświetlony i działa dobrze. Próbowałem też zadzwonić -setNeedsDisplaypo zmianie koloru, to nie miało żadnego efektu.

Jak zmusić przycisk do zmiany koloru tła?

MartinMoizard
źródło

Odpowiedzi:

411

Można zastąpić UIButton„s setHighlightedmetody.

Cel C

- (void)setHighlighted:(BOOL)highlighted {
    [super setHighlighted:highlighted];

    if (highlighted) {
        self.backgroundColor = UIColorFromRGB(0x387038);
    } else {
        self.backgroundColor = UIColorFromRGB(0x5bb75b);
    }
}

Swift 3.0 i Swift 4.1

override open var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? UIColor.black : UIColor.white
    }
}
Thomas Decaux
źródło
Tak. To miły sposób na zrobienie tego. Ponieważ możesz zdefiniować kilka podobnych przycisków.
Paul Brewczynski
3
Tylko pytanie dla początkujących, gdzie podklasowałbyś tę metodę przycisku? Jeśli mam przycisk w kontrolerze widoku o nazwie ConversionViewController, jak mam ustawić przycisk, aby zmienić kolor tła po podświetleniu lub dotknięciu? Czy podklasowałbym setHIghlighted w COnversionViewController?
Beanno1116
Znalazłem więc jeden problem z tą odpowiedzią. Jeśli chcesz, aby ten sam kolor był dostępny po wybraniu przycisku, wówczas setHighlighted zostanie wywołany po ustawieniu SetSelected, a tym samym zastąpi wybrany styl. Powyższe rozwiązanie może być lepsze, jeśli chcesz również wybrać przycisk
HaloZero,
3
@YakivKovalskiy zakładając, że używasz podklasy, możesz dodać dwie właściwości UIColor, np. NormalBackground i podświetlony Background, a następnie odpowiednio przypisać self.backgroundColor = normalBackground lub podświetlony Background. Nie zapomnij dodać metody init dla łatwości użycia, np. InitWithBackground: podświetloneBackground:
SK.
2
Ładne rozwiązanie, tylko jedna sugestia:backgroundColor = isHighlighted ? .lightGray : .white
Fantini
298

Nie jestem pewien, czy ten rodzaj rozwiązuje to, czego szukasz, czy pasuje do ogólnego krajobrazu programistycznego, ale pierwszą rzeczą, którą spróbowałbym, byłaby zmiana koloru tła przycisku na zdarzeniu touchDown.

Opcja 1:

Potrzebne byłyby dwa zdarzenia do przechwycenia, UIControlEventTouchDown byłby potrzebny, gdy użytkownik naciśnie przycisk. UIControlEventTouchUpInside i UIControlEventTouchUpOutside będą dostępne po zwolnieniu przycisku, aby przywrócić go do normalnego stanu

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

Opcja 2:

Zwróć obraz wykonany z żądanego koloru podświetlenia. To może być także kategoria.

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

a następnie zmień podświetlony stan przycisku:

[myButton setBackgroundImage:[self imageWithColor:[UIColor greenColor]] forState:UIControlStateHighlighted];
Tim
źródło
3
Dodaj UIControlEventTouchUpOutside i UIControlEventTouchCancel do buttonHighlight: lista zdarzeń i zawsze będzie działać.
Evgen Bodunov
Opcja druga jest najlepsza, jaką do tej pory znalazłem. Myślę jednak, że w tym przypadku storyboardy mają swoje zalety!
Jack Solomon
Odpowiedź Thomasa jest lepsza i tego też używam
Van Du Tran
26
Jeśli używasz layer.cornerRadiusi idziesz z opcją # 2, musisz upewnić się, że jest ustawiona wartość clipsToBoundstrue, aby zaokrąglić również rogi obrazu.
Sky
3
Jeśli ktoś zatrzyma się i potrzebuje odpowiedzi w Swift: stackoverflow.com/questions/26600980/…
zimuje
94

Nie ma potrzeby zastępowania highlightedjako obliczonej właściwości. Za pomocą obserwatora właściwości można wywołać zmianę koloru tła:

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

Szybki 4

override open var isHighlighted: Bool {
    didSet {
        backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white
    }
}
Aleksejs Mjaliks
źródło
1
Nigdy nie korzystałem z takiej funkcjonalności. Czy możesz wyjaśnić, dokąd to idzie? Czy jest to w funkcji IBAction buttonPress czy w viewDidLoad?
Dave G
Co się stanie, jeśli mam wiele przycisków UIB w różnych kolorach?
Slavcho,
6
@Dave G, tworzysz nową podklasę UIButton, klikając File>New>File>Cocoa Touch Classi ustawiając ją na subclass of UIButton. Nazwij plik np. CustomButton, Który stanie się zarówno nazwą pliku, jak i nazwą klasy. Wewnątrz tego pliku umieść override var highlightedkod pokazany powyżej. W ostatnim kroku ustaw UIButton w interfejsie Konstruktora, aby używał tej CustomButtonpodklasy, przechodząc do strony Właściwość, na której jest napisane „Klasa niestandardowa” i ma rozwijane pole. Powie „UIButton” szarymi literami. Lista rozwijana powinna zawierać CustomButton. Wybierz to, a przycisk jest teraz podklasą.
James Toomey
Dlaczego nikt nie wspomniał, że seter jest wywoływany tylko po naciśnięciu przycisku, ale nie podczas początkowego układu! Więc domyślnie nie ma koloru, dopóki nie dotkniesz przycisku.
Dmitrii
Aby więc działało, musisz również wyraźnie zadzwonić isHighlighted = falsegdzieś na początku (na przykład podczas inicjalizacji).
Dmitrii
49

Przydatne ogólne rozszerzenie w 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
źródło
45

W Swift możesz zastąpić akcesorium podświetlonej (lub wybranej) właściwości zamiast przesłonić metodę setHighlighted

override var highlighted: Bool {
        get {
            return super.highlighted
        }
        set {
            if newValue {
                backgroundColor = UIColor.blackColor()
            }
            else {
                backgroundColor = UIColor.whiteColor()
            }
            super.highlighted = newValue
        }
    }
Jake Hall
źródło
To całkowicie działa, ale jestem zdezorientowany, jak udało ci się to rozgryźć? O ile mi wiadomo, parametrów nie ma w dokumentacji ani w UIButton.h.
shimizu
1
Jest to szybka składnia, która emuluje zachowanie nadpisującego setHightlighted w celu c. Zobacz dokumentację o właściwościach obliczeniowych tutaj developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Jake Hall
11
W szybki sposób można użyć didSet
Dam
1
Dodałem przykład z obserwatorem właściwości: stackoverflow.com/a/29186375/195173 .
Aleksejs Mjaliks
Myślę, że @shimizu pytało, skąd wiedziałeś, że highlightedjest własnością na UIButton. Odpowiedź jest taka, że ​​jest to właściwość UIControl, z której dziedziczy UIButton.
Adam Johns
25

Zastąp podświetloną zmienną. Dodanie @IBInspectablesprawia, że ​​edytujesz podświetlony kolor tła w serii ujęć, który również jest fajny.

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
        }
    }
}
zacier
źródło
20

bardziej kompaktowe rozwiązanie (na podstawie odpowiedzi @ 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()
    }
}

Jeśli nie chcesz przesłonić, jest to zaktualizowana wersja odpowiedzi @ 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
źródło
@FedericoZanetello to zastąpi to Podświetlone we wszystkich przyciskach w Twojej aplikacji, co moim zdaniem nie jest dobrym rozwiązaniem. pójdę z odpowiedzią Timura.
Usama bin Attique,
13

Rozszerzenie UIButton ze składnią 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)
    }}

Używaj go jak:

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

Oryginalna odpowiedź: https://stackoverflow.com/a/30604658/3659227

Politycznie niezależny
źródło
10

Oto podejście w Swift, wykorzystujące rozszerzenie UIButton, aby dodać IBInspectable, o nazwie highlightedBackgroundColor. Podobny do podklasy, bez wymagania podklasy.

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

Mam nadzieję, że to pomoże.

Fostah
źródło
1
W przypadku wersji 2.0 należy zaktualizować wywołanie obiektu objc_setAssociatedObject, aby użyć wyliczenia: objc_setAssociatedObject (self, & NormalBackgroundColorKey, newValue, .OBJC_ASSOCIATION_RETAIN)
Eli Burke
Zdecydowanie najlepszy sposób w Swift, jeśli chcesz zachować wszystko w Storyboard.
davidethell
1
Wolę używać podklasy zamiast rozszerzenia, ponieważ wpłynie to na całą aplikację
Hossam Ghareeb 27.04.16
9

Moje najlepsze rozwiązanie dla Swift 3+ bez podklas.

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

Dzięki temu rozszerzeniu można łatwo zarządzać kolorami dla różnych stanów i automatycznie wyciszy Twój normalny kolor, w przypadku braku wyróżnionego koloru.

button.setBackgroundColor(.red, for: .normal)
Timur Bernikowicz
źródło
4

AKTUALIZACJA:

Użyj biblioteki UIButtonBackgroundColor Swift.

STARY:

Użyj pomocników poniżej, aby utworzyć obraz o wymiarach 1 x 1 x 1 piksel z kolorem wypełnienia w skali szarości:

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

lub kolor wypełnienia RGB:

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

Następnie użyj tego, imageaby ustawić obraz tła przycisku:

[button setBackgroundImage:image forState:UIControlStateNormal];

Pomocnicy

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

Uwaga: ACUjest prefiksem klasy mojej biblioteki statycznej Cocoa Touch o nazwie Acani Utilities, gdzie AC oznacza Acani, a U oznacza Utilities.

ma11hew28
źródło
4

Spróbuj tego !!!!

Dla zdarzenia TouchedDown ustaw jeden kolor, a dla TouchUpInside ustaw drugi.

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

- (IBAction)touchUpInside:(id)sender {
    NSLog(@"TouchUpInside");
    btn1.backgroundColor=[UIColor whiteColor];    
}
Karan Alangat
źródło
2
Pracował dla mnie. Musiałem tylko dodać, - (IBAction)onButtonTouchDragOutside:(UIButton *)sender {aby upewnić się, że kolor nie pozostanie włączony, gdy użytkownik przypadkowo wyciągnie palec z przycisku.
SudoPlz
4

Podklasuj przycisk UIB i dodaj właściwości, które można sprawdzić, dla wygodnego użycia (napisane w 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
źródło
3

Możesz podklasować UIButton i zrobić niezły 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

Uwagi (To jest przykład, wiem, że są problemy i oto kilka)

Użyłem NSMutableDictionay do przechowywania UIColor dla każdego stanu, muszę zrobić nieprzyjemną konwersję tekstu dla klucza, ponieważ UIControlState nie jest ładną prostą int. Jeśli to tam możesz zainicjować tablicę z tyloma obiektami i użyć stanu jako indeksu.

Z tego powodu wielu ma trudności z np. Wybraniem i wyłączeniem przycisku, potrzeba nieco więcej logiki.

Kolejny problem polega na tym, że jeśli próbujesz ustawić wiele kolorów jednocześnie, nie próbowałem za pomocą przycisku, ale jeśli możesz to zrobić, może nie działać

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

Zakładam, że to StoryBoard, nie ma init, initWithFrame, więc dodaj je, jeśli ich potrzebujesz.

Stal z recyklingu
źródło
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 , dzięki @Maverick

dengST30
źródło
3

Detale

  • Xcode 11.1 (11A1027), Swift 5

Rozwiązanie

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

Stosowanie

button.setBackground(.green, for: .normal)
Wasilij Bodnarchuk
źródło
2

Spróbuj tego, jeśli masz obraz:

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

lub sprawdź, czy showsTouchWhenHighlightedto ci wystarczy.

Siby
źródło
Próbowałem grać z programami TouchThenWhighlighted, ale to nie pomogło. Nie chcę używać setBackgroundImage: forState :. W rzeczywistości próbowałem użyć koloru tła, aby nie używać żadnego obrazu.
MartinMoizard
2

Aby rozwiązać ten problem, stworzyłem kategorię do obsługi backgroundColorstanów za pomocą UIButtons:
ButtonBackgroundColor-iOS

Możesz zainstalować kategorię jako kapsuła .

Łatwy w użyciu z Objective-C

@property (nonatomic, strong) UIButton *myButton;

...

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

Jeszcze łatwiejszy w użyciu dzięki Swift :

import ButtonBackgroundColor

...

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

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

Polecam zaimportować kapsułę z:

platform :ios, '8.0'
use_frameworks!

pod 'ButtonBackgroundColor', '~> 1.0'

Korzystanie z use_frameworks! w Podfile ułatwia korzystanie ze swoich strąków dzięki Szybkiemu i celowi-C.

WAŻNY

Napisałem też post na blogu z dodatkowymi informacjami.

Gabriel.Massana
źródło
2
class CustomButton: UIButton {

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

}
evya
źródło
2

Posługiwać się https://github.com/swordray/UIButtonSetBackgroundColorForState

Dodaj do Podfile przy użyciu CocoaPods

pod "UIButtonSetBackgroundColorForState"

Szybki

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

Cel C

[button setBackgroundColor:[UIColor redColor] forState:UIControlStateHighlighted];
miecznik
źródło
1

Spróbuj tintColor:

_button.tintColor = [UIColor redColor];
jjv360
źródło
Czy na pewno jest to powiązane w IB? Co otrzymasz, jeśli to zrobisz NSLog(@"%@", _button);?
jjv360
1
To nie zadziała, jeśli używasz UIButtonTypeCustom.
JaredH
1

Oto kod w Swift, aby wybrać stan przycisku:

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

Przykład:

    self.button.setImage(self.imageWithColor(UIColor.blackColor()), forState: .Highlighted)
Mike Zriel
źródło
1

Upuść go i możesz zacząć:
* Proerty można ustawić w IB, a jeśli nie zostanie ustawione podświetlone tło, tło nie zmieni się po naciśnięciu

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
        }
    }
}
but
źródło
1

Poniższe UIIImagerozszerzenie wygeneruje obiekt obrazu o określonym parametrze koloru.

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

Przykładowe użycie przycisku można zastosować do obiektu przycisku jako:

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
źródło
1

proste jest użycie TYLKO tego rozszerzenia UIButton

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

}

i użyj tego

 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
źródło
0

jeśli nie zastąpisz, po prostu ustaw dwa działania touchDown touchUpInside

Roman Bambura
źródło
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
źródło
0

w Swift 5

Dla tych, którzy nie chcą używać kolorowego tła, aby pobić wybrany stan

Po prostu możesz pokonać problem za pomocą instrukcji #Selector i if, aby łatwo zmienić kolory UIButton dla każdego stanu

Na przykład:

    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
źródło