Czy można zmienić kolor tła UIButtons?

105

Ten mnie zaskoczył.

Czy w ogóle jest możliwa zmiana koloru tła przycisku UIButton w kakao na iPhone'a? Próbowałem ustawić kolor tła, ale zmienia to tylko rogi. setBackgroundColor:wydaje się być jedyną dostępną metodą na takie rzeczy.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];
dubbeat
źródło
czy możesz naprawić obraz lub go usunąć? kthx;)
stigi
o-0 hmmmm ....., obraz był w porządku, ale teraz już się nie pojawi. Właśnie go
usunąłem
To jest duplikat stackoverflow.com/questions/372731/ ...
Brad Larson
Rozwiązuję ten problem w moim poprzednim poście, sprawdź link [Dynamicznie zmień obramowanie lub tło UIButton] [1] [1]: stackoverflow.com/questions/9733213/…
IMMORTAL
dobry samouczek i przykładowy kod można znaleźć tutaj cimgf.com/2010/01/28/...
Shamsudheen TK

Odpowiedzi:

160

Można to zrobić programowo, tworząc replikę:

loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
[loginButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
loginButton.backgroundColor = [UIColor whiteColor];
loginButton.layer.borderColor = [UIColor blackColor].CGColor;
loginButton.layer.borderWidth = 0.5f;
loginButton.layer.cornerRadius = 10.0f;

edycja: oczywiście, musiałbyś #import <QuartzCore/QuartzCore.h>

edycja: dla wszystkich nowych czytelników należy również rozważyć kilka opcji dodanych jako „inna możliwość”. do rozważenia.

Ponieważ jest to stara odpowiedź, zdecydowanie polecam przeczytanie komentarzy dotyczących rozwiązywania problemów

Stian Storrvik
źródło
Tego właśnie szuka PO.
Steven
4
Słodkie! Ze wszystkich solów, które znalazłem, to ten, z którym poszedłem. Dla wyjaśnienia, stworzenie „repliki” oznacza użycie kwarcu do narysowania zaokrąglonego prostokąta w niestandardowym przycisku, zamiast używania przycisku typu RoundedRect. Na początku pomyślałem, że oznacza to w jakiś sposób zrobienie kopii zaokrąglonego prostokąta w innym kolorze, aby zasymulować zmianę koloru bg.
daver
1
Działało idealnie, najlepsza odpowiedź na OP. Dzięki za udostępnienie.
Bram
@daver: Ta odpowiedź jest tak popularna, że ​​musi mieć zalety, których mi brakuje. Jak można zmienić kolor tła w zależności od stanu? Przypuszczalnie należy wyraźnie zmieniać kolor tła za każdym razem, gdy zmienia się stan. Mój przycisk jest wyłączony po naciśnięciu, dopóki usługa internetowa nie odpowie. Czy muszę zmienić kolor, aby podświetlić kolor w prasie i zmienić czasomierz na kolor wyłączony, czekając na odpowiedź WS? Jeśli nie rozumiem, czy ktoś może wyjaśnić. Dzięki Polly.
Polly,
1
@Polly: Przepraszam, że nie widziałem Twojego komentarza wcześniej, ale jeśli nadal jesteś zainteresowany, oto co zrobiłem: podklasa UIButton i zastąpienie drawRect: aby narysować zaokrąglony prostokąt przy użyciu niektórych UIBezierPaths. Po narysowaniu wypełnij go gradientem za pomocą CGGradientCreateWithColorComponents (). Jednym z argumentów tej funkcji jest 4-elementowa tablica liczb zmiennoprzecinkowych (odpowiadających R, G, B i alfa). Zdefiniowałem 2 tablice kolorów, po jednej dla każdego stanu, i wybrałem odpowiednią w drawRect na podstawie stanu przycisku.
daver
59

Mam inne podejście,

[btFind setTitle:NSLocalizedString(@"Find", @"") forState:UIControlStateNormal];    
[btFind setBackgroundImage:[CommonUIUtility imageFromColor:[UIColor cyanColor]] 
        forState:UIControlStateNormal];
btFind.layer.cornerRadius = 8.0;
btFind.layer.masksToBounds = YES;
btFind.layer.borderColor = [UIColor lightGrayColor].CGColor;
btFind.layer.borderWidth = 1;

Ze strony CommonUIUtility,

+ (UIImage *) imageFromColor:(UIColor *)color {
    CGRect rect = CGRectMake(0, 0, 1, 1);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    //  [[UIColor colorWithRed:222./255 green:227./255 blue: 229./255 alpha:1] CGColor]) ;
    CGContextFillRect(context, rect);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

Nie zapomnij #import <QuartzCore/QuartzCore.h>

karim
źródło
2
Niezłe. Okazało się, że muszę dodaćbtFind.layer.borderWidth = 1;
DefenestrationDay,
Podoba mi się to rozwiązanie, ale w tej chwili nie mogę z niego skorzystać. Pojawia się błąd, ponieważ nie można znaleźć „CommonUIUtility”. Google po prostu daje mi informacje o zaćmieniu, ale myślę, że powinno to być w QuartzCore? Jakieś pomysły?
Stephan
Nie, to jest klasa zdefiniowana przez użytkownika do wykonywania typowych elementów interfejsu użytkownika w aplikacji. Piszesz metodę imageFromColor we własnej klasie.
karim
1
Pachnie metody kategorii na UIButton: setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB
3
To takie głupie, że jesteśmy na iOS 7 i to NADAL najczystszy sposób na dodanie koloru tła
dmur
32

Zakładam, że mówisz o UIButton z UIButtonTypeRoundedRect? Nie możesz zmienić tego koloru tła. Kiedy próbujesz zmienić kolor tła, zmieniasz raczej kolor prostokąta, na którym jest narysowany przycisk (co zwykle jest jasne). Więc są dwa sposoby. Albo utworzysz podklasę UIButton i nadpiszesz jej-drawRect: metodę, albo tworzysz obrazy dla różnych stanów przycisków (co jest w porządku).

Jeśli ustawisz obrazy tła w Interface Builder, powinieneś zauważyć, że IB nie obsługuje ustawiania obrazów dla wszystkich stanów, które może mieć przycisk, więc zalecam ustawienie obrazów w kodzie w następujący sposób:

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setBackgroundImage:[UIImage imageNamed:@"normal.png"] forState:UIControlStateNormal];
[myButton setBackgroundImage:[UIImage imageNamed:@"disabled.png"] forState:UIControlStateDisabled];
[myButton setBackgroundImage:[UIImage imageNamed:@"selected.png"] forState:UIControlStateSelected];
[myButton setBackgroundImage:[UIImage imageNamed:@"higligted.png"] forState:UIControlStateHighlighted];
[myButton setBackgroundImage:[UIImage imageNamed:@"highlighted+selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)];

Ostatnia linia pokazuje, jak ustawić obraz dla wybranego i podświetlonego stanu (tego IB nie może ustawić). Nie potrzebujesz wybranych obrazów (wiersz 4 i 6), jeśli przycisk nie potrzebuje wybranego stanu.

stigi
źródło
Dzięki za wyjaśnienie. Tylko krótkie pytanie. Jeśli nadpisuję metodę drawrect, myślę, że wymagałoby to użycia biblioteki rysunków? Coś samego w liniach programistycznego rysowania zaokrąglonego prostokąta i wypełniania go kolorem?
dubbeat
2
Właśnie wyszukałem w Google krótkie zapytanie „iphone drawrect round rogi” i znalazłem to: iphonedevelopment.blogspot.com/2008/11/ ... Sprawdź metodę drawrect, aby zobaczyć przykład, jak narysować okrągły prostokąt. Możesz użyć CGContextSetFillColorWithColori, CGContextFillPathaby wypełnić narysowaną ścieżkę CGContextAddArcToPoint.
stigi
2
+50 za wskazanie potencjału maskowania bitów dla stanów kontrolnych, np .: forState:(UIControlStateHighlighted | UIControlStateSelected)Cheers.
NSTJ
28

Inna możliwość:

  1. Utwórz przycisk UIButton w konstruktorze interfejsów.
  2. Nadaj mu typ „Niestandardowy”
  3. Teraz w IB można zmienić kolor tła

Jednak przycisk jest kwadratowy, a nie tego chcemy. Utwórz IBOutlet z odwołaniem do tego przycisku i dodaj następujące elementy do metody viewDidLoad:

[buttonOutlet.layer setCornerRadius:7.0f];
[buttonOutlet.layer setClipToBounds:YES];

Nie zapomnij zaimportować QuartzCore.h

wubbe
źródło
7
Perfekcyjnie, dziękuję! Nie jestem pewien, czy to z powodu wersji iOS, której używam (5.1), ale setClipToBounds nie był dostępny. Zamiast tego użyłem buttonOutlet.layer.masksToBounds = TRUE;
iforce2d
Kiedy dodam ten kod, pokazuje zaokrąglony prostokąt, ale kiedy go kliknę, przycisk nie odwraca podświetlenia. Co się dzieje?
Będzie
Problem z tym podejściem polega na tym, że nie można ustawić koloru tła dla podświetlonego stanu przycisku.
ch3rryc0ke
17

Podklasa UIButton i przesłonięcie metod setHighlighted i setSelected

-(void) setHighlighted:(BOOL)highlighted {

  if(highlighted) {
    self.backgroundColor = [self.mainColor darkerShade];
  } else {
    self.backgroundColor = self.mainColor;
  }
  [super setHighlighted:highlighted];
}

-(void) setSelected:(BOOL)selected {

  if(selected) {
    self.backgroundColor = [self.mainColor darkerShade];
  } else {
    self.backgroundColor = self.mainColor;
  }
  [super setSelected:selected];
}

Moja metoda darkerShade należy do takiej kategorii UIColor

-(UIColor*) darkerShade {

  float red, green, blue, alpha;
  [self getRed:&red green:&green blue:&blue alpha:&alpha];

  double multiplier = 0.8f;
  return [UIColor colorWithRed:red * multiplier green:green * multiplier blue:blue*multiplier alpha:alpha];
}
Mugunth
źródło
7

kolorowy UIButton

Jeśli nie chcesz używać obrazów i chcesz, aby wyglądał dokładnie tak, jak styl zaokrąglonego prostokąta, spróbuj tego. Po prostu umieść UIView nad przyciskiem UIButton, z identyczną ramką i maską automatycznej zmiany rozmiaru, ustaw alfa na 0,3 i ustaw kolor tła. Następnie użyj poniższego fragmentu, aby przyciąć zaokrąglone krawędzie z kolorowego widoku nakładki. Odznacz także pole wyboru „Włączono interakcję z użytkownikiem” w IB na UIView, aby umożliwić zdarzeniom dotykowym kaskadę w dół do przycisku UIButton poniżej.

Jednym z efektów ubocznych jest to, że tekst również zostanie pokolorowany.

#import <QuartzCore/QuartzCore.h>

colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;
Jacob Jennings
źródło
7

Inna możliwość (najlepsze i najpiękniejsze imho):

Utwórz UISegmentedControl z 2 segmentami w wymaganym kolorze tła w Interface Builder. Ustaw typ na „bar”. Następnie zmień go tak, aby miał tylko jeden segment. Kreator interfejsów nie akceptuje jednego segmentu, więc musisz to zrobić programowo.

Dlatego utwórz IBOutlet dla tego przycisku i dodaj to do viewDidLoad swojego widoku:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Teraz masz piękny błyszczący, kolorowy przycisk z określonym kolorem tła. W przypadku działań użyj zdarzenia „wartość zmieniona”.

(Znalazłem to na http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ ). Dzięki Chris!

wubbe
źródło
5

Cóż, jestem w 99% przekonany, że nie można tak po prostu przejść i zmienić koloru tła przycisku UIB. Zamiast tego musisz samodzielnie zmienić obrazy tła, co moim zdaniem jest uciążliwe. Jestem zdumiony, że musiałem to zrobić.

Jeśli się mylę lub jest lepszy sposób bez konieczności ustawiania obrazów tła, daj mi znać

[random setBackgroundImage:[UIImage imageNamed:@"toggleoff.png"] forState:UIControlStateNormal];
    [random setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];


[random setBackgroundImage:[UIImage imageNamed:@"toggleon.png"] forState:UIControlStateNormal];
    [random setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
dubbeat
źródło
5
Masz całkowitą rację. Jest to uciążliwe i powinno zająć kilka minut zamiast kłopotów z tworzeniem obrazów. Poza tym, jeśli twój guzik jest okrągły, to jeszcze trudniej zrobić ... Taki ból.
Henley Chiu
2

Zgodnie z sugestią @EthanB i @karim tworzącym prostokąt wypełniony z tyłu, właśnie utworzyłem kategorię dla UIButton, aby to osiągnąć.

Wystarczy wpisać kod kategorii: https://github.com/zmonteca/UIButton-PLColor

Stosowanie:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

Opcjonalne do użycia przez państwa:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
zmonteca
źródło
2

Możesz także dodać CALayer do przycisku - możesz z nimi zrobić wiele rzeczy, w tym kolorową nakładkę, w tym przykładzie zastosowano zwykłą warstwę koloru, którą możesz łatwo stopniować. Należy pamiętać, że dodane warstwy zasłaniają te pod spodem

+(void)makeButtonColored:(UIButton*)button color1:(UIColor*) color
{

    CALayer *layer = button.layer;
    layer.cornerRadius = 8.0f;
    layer.masksToBounds = YES;
    layer.borderWidth = 4.0f;
    layer.opacity = .3;//
    layer.borderColor = [UIColor colorWithWhite:0.4f alpha:0.2f].CGColor;

    CAGradientLayer *colorLayer = [CAGradientLayer layer];
    colorLayer.cornerRadius = 8.0f;
    colorLayer.frame = button.layer.bounds;
    //set gradient colors
    colorLayer.colors = [NSArray arrayWithObjects:
                         (id) color.CGColor,
                         (id) color.CGColor,
                         nil];

    //set gradient locations
    colorLayer.locations = [NSArray arrayWithObjects:
                            [NSNumber numberWithFloat:0.0f],
                            [NSNumber numberWithFloat:1.0f],
                            nil];


    [button.layer addSublayer:colorLayer];

}
gheese
źródło
Znakomity!!!!!! Ale nie mógł zostać sprawdzony kilka razy przeciwko temu samemu buttonowi. Możliwe, ale nowe warstwy są dodawane wielokrotnie.
Valeriy Van
@StanJames: Zmiany w kodzie powinny być sugerowane przez komentarz (lub, jeśli to stosowne, przez twoją własną odpowiedź).
mafso
1

dodaj drugi cel dla UIButtonfor UIControlEventTouchedi zmień UIButtonkolor tła. Następnie zmień go z powrotem w UIControlEventTouchUpInsidecelu;

Shaun
źródło
1

Aby uzyskać profesjonalne i dobrze wyglądające przyciski, możesz sprawdzić ten niestandardowy komponent przycisków . Możesz go używać bezpośrednio w swoich widokach i widokach tabel lub zmodyfikować kod źródłowy, aby spełniał Twoje potrzeby. Mam nadzieję że to pomoże.

Ahmet Ardal
źródło
1

To nie jest tak eleganckie jak podklasa UIButton, jednak jeśli chcesz po prostu czegoś szybkiego - zrobiłem niestandardowy przycisk, a następnie obraz 1 na 1 piksel w kolorze, który chciałbym, aby przycisk był i ustawiłem tło przycisku do tego obrazu dla stanu podświetlonego - działa na moje potrzeby.

SMSidat
źródło
1

Wiem, że zadawano to dawno temu, a teraz jest nowy UIButtonTypeSystem. Ale nowsze pytania są oznaczane jako duplikaty tego pytania, więc oto moja nowsza odpowiedź w kontekście przycisku systemu iOS 7, użyj .tintColorwłaściwości.

let button = UIButton(type: .System)
button.setTitle("My Button", forState: .Normal)
button.tintColor = .redColor()
DonnaLea
źródło
0

[myButton setBackgroundColor:[UIColor blueColor]]; [myButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

Można zmienić w ten sposób lub przejść do Storyboard i zmienić tło w opcjach po prawej stronie.

Vinicius Carvalho
źródło
0

Swift 3:

        static func imageFromColor(color: UIColor, width: CGFloat, height: CGFloat) -> UIImage {
            let rect = CGRect(x: 0, y: 0, width: width, height: height)
            UIGraphicsBeginImageContext(rect.size)
            let context = UIGraphicsGetCurrentContext()!
            context.setFillColor(color.cgColor)
            context.fill(rect)
            let img = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            return img
        }

        let button = UIButton(type: .system)
        let image = imageFromColor(color: .red, width: 
        button.frame.size.width, height: button.frame.size.height)
        button.setBackgroundImage(image, for: .normal)
pawurb
źródło
Byłaby to znacznie bardziej użyteczna odpowiedź, gdybyś powiedział, jak wywołać lub wykorzystać kod, który tam umieściłeś. Czy trafia do rozszerzenia UIButton?
Michael Dautermann