Ist es möglich, die Hintergrundfarbe eines UIButtons zu ändern?

105

Dieser hat mich verblüfft.

Ist es überhaupt möglich, die Hintergrundfarbe eines UIButton in Cocoa für iPhone zu ändern? Ich habe versucht, die Hintergrundfarbe einzustellen, aber sie ändert nur die Ecken. setBackgroundColor:scheint die einzige verfügbare Methode für solche Dinge zu sein.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];
Dubbeat
quelle
Können Sie das Bild reparieren oder entfernen? kthx;)
stigi
o-0 hmmmm ....., das Bild war in Ordnung, aber jetzt wird es nicht mehr angezeigt. Gerade gelöscht
Dubbeat
Dies ist ein Duplikat von stackoverflow.com/questions/372731/…
Brad Larson
Ich löse dieses Problem in meinem vorherigen Beitrag. Bitte überprüfen Sie den Link [Rand oder Hintergrund eines UIButton dynamisch ändern] [1] [1]: stackoverflow.com/questions/9733213/…
IMMORTAL
Gutes Tutorial und Beispielcode finden Sie hier cimgf.com/2010/01/28/…
Shamsudheen TK

Antworten:

160

Dies kann programmgesteuert erfolgen, indem eine Replik erstellt wird:

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;

edit: natürlich müsstest du #import <QuartzCore/QuartzCore.h>

Bearbeiten: Für alle neuen Leser sollten Sie auch einige Optionen in Betracht ziehen, die als "eine andere Möglichkeit" hinzugefügt wurden. für Sie Überlegung.

Da dies eine alte Antwort ist, empfehle ich dringend, Kommentare zur Fehlerbehebung zu lesen

Stian Storrvik
quelle
Das ist es, wonach das OP sucht.
Steven
4
Süss! Von allen Lösungen, die ich gefunden habe, ist dies die, mit der ich gegangen bin. Zur Verdeutlichung bedeutet das Erstellen einer "Replik", dass Sie mit Quarz ein abgerundetes Rechteck in einer benutzerdefinierten Schaltfläche zeichnen, anstatt eine Schaltfläche vom Typ "RoundedRect" zu verwenden. Zuerst dachte ich, es würde irgendwie bedeuten, ein Duplikat eines abgerundeten Rect mit einer anderen Farbe zu erstellen, um das Ändern der BG-Farbe zu simulieren.
Daver
1
Perfekt funktioniert, beste Antwort auf OP. Danke für das Teilen.
Bram
@daver: Diese Antwort ist so beliebt, dass sie einen Verdienst haben muss, den ich vermisse. Wie kann man die Hintergrundfarbe je nach Zustand ändern? Vermutlich muss man die Hintergrundfarbe jedes Mal explizit ändern, wenn sich der Zustand ändert. Meine Schaltfläche wird beim Drücken deaktiviert, bis ein Webdienst antwortet. Muss ich mich ändern, um die Farbe beim Drücken hervorzuheben, und den Timer auf deaktivierte Farbe ändern, während ich darauf warte, dass das ws antwortet? Wenn mir der Punkt fehlt, kann jemand bitte erklären. Danke Polly.
Polly
1
@Polly: Entschuldigung, ich habe Ihren Kommentar nicht früher gesehen, aber wenn Sie immer noch interessiert sind, habe ich Folgendes getan: Unterklasse UIButton und Überschreibung drawRect: um das abgerundete Rechteck mit einigen UIBezierPaths zu zeichnen. Füllen Sie es nach dem Zeichnen mit CGGradientCreateWithColorComponents () mit einem Farbverlauf. Eines der Argumente für diese Funktion ist ein 4-Element-Array von Floats (entsprechend R, G, B und Alpha). Ich habe 2 Farbarrays definiert, eines für jeden Status, und das entsprechende in drawRect basierend auf dem Schaltflächenstatus ausgewählt.
Daver
59

Ich habe einen anderen Ansatz,

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

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

Vergiss es nicht #import <QuartzCore/QuartzCore.h>

Karim
quelle
2
Schön. Ich fand, ich musste einenbtFind.layer.borderWidth = 1;
DefenestrationDay
Ich mag diese Lösung, aber im Moment kann ich sie nicht verwenden. Ich erhalte eine Fehlermeldung, weil "CommonUIUtility" nicht gefunden werden kann. Google gibt mir nur Eclipse-Sachen, aber ich denke, es sollte im QuartzCore sein? Irgendwelche Ideen?
Stephan
Nein, das ist eine benutzerdefinierte Klasse für allgemeine UI-Aufgaben in der App. Sie schreiben die imageFromColor-Methode in Ihre eigene Klasse.
Karim
1
Riecht nach einer Kategoriemethode auf UIButton : setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB
3
Es ist so albern, dass wir auf iOS 7 sind und dies ist immer noch der sauberste Weg, um eine Hintergrundfarbe hinzuzufügen
dmur
32

Ich nehme an, Sie sprechen von einem UIButton mit UIButtonTypeRoundedRect? Sie können die Hintergrundfarbe davon nicht ändern. Wenn Sie versuchen, die Hintergrundfarbe zu ändern, ändern Sie eher die Farbe des Rechtecks, auf das die Schaltfläche gezeichnet ist (was normalerweise klar ist). Es gibt also zwei Möglichkeiten. Entweder unterklassifizieren Sie UIButton und überschreiben seine -drawRect:Methode, oder Sie erstellen Bilder für die verschiedenen Schaltflächenzustände (was vollkommen in Ordnung ist).

Wenn Sie die Hintergrundbilder in Interface Builder festlegen, sollten Sie beachten, dass IB das Festlegen von Bildern nicht für alle Zustände unterstützt, die die Schaltfläche haben kann. Ich empfehle daher, die Bilder in Code wie folgt festzulegen:

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

Die letzte Zeile zeigt, wie ein Bild für den ausgewählten und hervorgehobenen Status festgelegt wird (das ist derjenige, den IB nicht festlegen kann). Sie benötigen die ausgewählten Bilder (Zeile 4 und 6) nicht, wenn Sie auf der Schaltfläche keinen ausgewählten Status benötigen.

stigi
quelle
Danke für die Erklärung. Nur eine kurze Frage. Wenn ich die Zeichnungsmethode überschreibe, würde ich wahrscheinlich eine Zeichnungsbibliothek verwenden? Etwas allein die Linien des programmgesteuerten Zeichnens eines abgerundeten Rechtecks ​​und des Füllens mit einer Farbe?
Dubbeat
2
Ich habe gerade eine kurze Google-Abfrage für "iPhone Drawrect Round Corner" durchgeführt und Folgendes gefunden: iphonedevelopment.blogspot.com/2008/11/… Überprüfen Sie die Drawrect-Methode für ein Beispiel zum Zeichnen eines runden Rect. Sie können den von gezeichneten Pfad verwenden CGContextSetFillColorWithColorund CGContextFillPathfüllen CGContextAddArcToPoint.
Stigi
2
+50 für den Hinweis auf das Bitmaskierungspotential für Kontrollzustände, dh: forState:(UIControlStateHighlighted | UIControlStateSelected)Prost.
NSTJ
28

Andere Möglichkeit:

  1. Erstellen Sie einen UIButton im Interface Builder.
  2. Geben Sie ihm den Typ "Benutzerdefiniert".
  3. In IB ist es jetzt möglich, die Hintergrundfarbe zu ändern

Die Schaltfläche ist jedoch quadratisch, und das ist nicht das, was wir wollen. Erstellen Sie ein IBOutlet mit einem Verweis auf diese Schaltfläche und fügen Sie der viewDidLoad-Methode Folgendes hinzu:

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

Vergessen Sie nicht, QuartzCore.h zu importieren

wubbe
quelle
7
Perfekt, danke! Ich bin nicht sicher, ob es an der von mir verwendeten iOS-Version (5.1) liegt, aber setClipToBounds war nicht verfügbar. Stattdessen habe ich buttonOutlet.layer.masksToBounds = TRUE verwendet.
iforce2d
Wenn ich diesen Code hinzufüge, wird ein abgerundetes Rechteck angezeigt, aber wenn ich darauf klicke, kehrt die Schaltfläche die Hervorhebung nicht um. Was ist los?
Will
Das Problem bei diesem Ansatz ist, dass Sie keine Hintergrundfarbe für den hervorgehobenen Status der Schaltfläche festlegen können.
ch3rryc0ke
17

Unterklasse UIButton und überschreiben die Methoden setHighlighted und 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];
}

Meine darkerShade-Methode gehört zu einer solchen UIColor-Kategorie

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

farbiger UIButton

Wenn Sie keine Bilder verwenden möchten und diese genau wie der abgerundete Rechteck-Stil aussehen sollen, versuchen Sie dies. Platzieren Sie einfach eine UIView über dem UIButton mit einem identischen Rahmen und einer Maske mit automatischer Größenänderung, setzen Sie das Alpha auf 0,3 und setzen Sie den Hintergrund auf eine Farbe. Verwenden Sie dann das folgende Snippet, um die abgerundeten Kanten von der farbigen Überlagerungsansicht abzuschneiden. Deaktivieren Sie außerdem das Kontrollkästchen "Benutzerinteraktion aktiviert" in IB in der UIView, damit Berührungsereignisse auf den darunter liegenden UIButton übertragen werden können.

Ein Nebeneffekt ist, dass Ihr Text auch eingefärbt wird.

#import <QuartzCore/QuartzCore.h>

colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;
Jacob Jennings
quelle
7

Eine andere Möglichkeit (das beste und schönste imho):

Erstellen Sie in Interface Builder ein UISegmentedControl mit 2 Segmenten in der erforderlichen Hintergrundfarbe. Setzen Sie den Typ auf 'bar'. Ändern Sie es dann in nur ein Segment. Der Interface Builder akzeptiert kein Segment, daher müssen Sie dies programmgesteuert tun.

Erstellen Sie daher ein IBOutlet für diese Schaltfläche und fügen Sie dieses dem viewDidLoad Ihrer Ansicht hinzu:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Jetzt haben Sie einen schönen glänzenden, farbigen Knopf mit der angegebenen Hintergrundfarbe. Verwenden Sie für Aktionen das Ereignis 'Wert geändert'.

(Ich habe dies auf http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ gefunden ). Danke Chris!

wubbe
quelle
5

Ich bin mir zu 99% sicher, dass Sie nicht einfach die Hintergrundfarbe eines UIButton ändern können. Stattdessen müssen Sie die Hintergrundbilder selbst ändern, was ich für schmerzhaft halte. Ich bin erstaunt, dass ich das tun musste.

Wenn ich falsch liege oder wenn es einen besseren Weg gibt, ohne Hintergrundbilder einstellen zu müssen, lassen Sie es mich bitte wissen

[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
quelle
5
Du hast absolut recht. Es ist ein Schmerz und etwas, das ein paar Minuten dauern sollte, anstatt mühsam Bilder zu erstellen. Plus, wenn Ihr Knopf rund ist, macht es noch schwieriger, dies auch zu tun ... Solch ein Schmerz.
Henley Chiu
2

Gemäß dem Vorschlag von @EthanB und dem Erstellen eines von hinten gefüllten Rechtecks ​​durch @karim habe ich gerade eine Kategorie für den UIButton erstellt, um dies zu erreichen.

Geben Sie einfach den Kategoriecode ein: https://github.com/zmonteca/UIButton-PLColor

Verwendung:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

Optionale Verwendung für Staaten:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
zmonteca
quelle
2

Sie können der Schaltfläche auch einen CALayer hinzufügen - Sie können viele Dinge damit tun, einschließlich einer Farbüberlagerung. In diesem Beispiel wird eine einfache Farbebene verwendet, mit der Sie die Farbe auch leicht abstufen können. Beachten Sie jedoch, dass hinzugefügte Ebenen die darunter liegenden Ebenen verdecken

+(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
quelle
Brillant!!!!!! Kann aber nicht mehrmals gegen denselben Knopf aufgerufen werden. Könnte, aber neue Ebenen werden immer wieder hinzugefügt.
Valeriy Van
@StanJames: Änderungen am Code sollten durch einen Kommentar (oder gegebenenfalls durch Ihre eigene Antwort) vorgeschlagen werden.
Mafso
1

ein zweites Ziel für das hinzufügen UIButtonfür UIControlEventTouchedund ändern UIButtonHintergrundfarbe. Ändern Sie es dann wieder im UIControlEventTouchUpInsideZiel.

Shaun
quelle
1

Für professionelle und gut aussehende Schaltflächen können Sie diese benutzerdefinierte Schaltflächenkomponente überprüfen . Sie können es direkt in Ihren Ansichten und Tabellenansichten verwenden oder den Quellcode so ändern, dass er Ihren Anforderungen entspricht. Hoffe das hilft.

Ahmet Ardal
quelle
1

Dies ist nicht so elegant wie das Unterordnen von UIButton. Wenn Sie jedoch nur etwas schnelles möchten - ich habe eine benutzerdefinierte Schaltfläche erstellt, dann ein 1 x 1 Pixel großes Bild mit der Farbe, die die Schaltfläche haben soll, und den Hintergrund festgelegt der Schaltfläche zu diesem Bild für den hervorgehobenen Zustand - funktioniert für meine Bedürfnisse.

SMSidat
quelle
1

Ich weiß, dass dies vor langer Zeit gefragt wurde und jetzt gibt es ein neues UIButtonTypeSystem. Neuere Fragen werden jedoch als Duplikate dieser Frage markiert. Hier ist meine neuere Antwort im Kontext einer iOS 7-Systemschaltfläche. Verwenden Sie die .tintColorEigenschaft.

let button = UIButton(type: .System)
button.setTitle("My Button", forState: .Normal)
button.tintColor = .redColor()
DonnaLea
quelle
0

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

Es ist möglich, auf diese Weise zu ändern oder das Storyboard aufzurufen und den Hintergrund für die Optionen auf der rechten Seite zu ändern.

Vinicius Carvalho
quelle
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
quelle
Dies wäre eine viel nützlichere Antwort, wenn Sie sagen würden, wie Sie den dort aufgestellten Code aufrufen oder verwenden sollen. Geht es in eine UIButton-Erweiterung?
Michael Dautermann