È possibile cambiare il colore di sfondo di un UIButtons?


105

Questo mi ha lasciato perplesso.

È possibile modificare il colore di sfondo di un pulsante UIB in Cocoa per iPhone. Ho provato a impostare il colore di sfondo ma cambia solo gli angoli. setBackgroundColor:sembra essere l'unico metodo disponibile per queste cose.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];

puoi correggere l'immagine o rimuoverla? kthx;)
stigi

o-0 hmmmm ....., l'immagine andava bene ma ora non viene più visualizzata. L'ho appena cancellato
doppiaggio


Ho risolto questo problema nel mio post precedente, per favore controlla il link [Cambia dinamicamente il bordo o il backgraound di un UIButton] [1] [1]: stackoverflow.com/questions/9733213/…
IMMORTAL

buon tutorial e codice di esempio trovati qui cimgf.com/2010/01/28/…
Shamsudheen TK

Risposte:


160

Questa operazione può essere eseguita a livello di codice creando una replica:

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;

modifica: ovviamente, dovresti #import <QuartzCore/QuartzCore.h>

modifica: a tutti i nuovi lettori, dovresti anche considerare alcune opzioni aggiunte come "un'altra possibilità". per te considerazione.

Poiché questa è una vecchia risposta, consiglio vivamente di leggere i commenti per la risoluzione dei problemi


Questo è ciò che sta cercando l'OP.
Steven

4
dolce! Di tutti i solni che ho trovato, questo è quello con cui sono andato. Come punto di chiarimento, creare una "replica" significa utilizzare Quartz per disegnare un rettangolo arrotondato in un pulsante personalizzato, piuttosto che utilizzare un pulsante di tipo RoundedRect. All'inizio ho pensato che significasse in qualche modo creare un duplicato di un rettangolo arrotondato con un colore diverso per simulare la modifica del colore bg.
daver

1
Ha funzionato perfettamente, migliore risposta a OP. Grazie per la condivisione.
Bram

@daver: questa risposta è così popolare che deve avere un merito che mi manca. Come si può cambiare il colore di sfondo in base allo stato? Presumibilmente si deve cambiare esplicitamente il colore di sfondo ogni volta che lo stato cambia. Il mio pulsante è disabilitato alla pressione fino a quando un servizio Web non risponde. Devo cambiare per evidenziare il colore sulla stampante e far cambiare il timer al colore disabilitato mentre aspetto che la ws risponda? Se mi manca il punto qualcuno può spiegare. Grazie Polly.
Polly

1
@Polly: Scusa non ho visto il tuo commento prima, ma se sei ancora interessato ecco cosa ho finito per fare: sottoclasse UIButton e sovrascrivi drawRect: per disegnare il rect arrotondato usando alcuni UIBezierPaths. Dopo aver disegnato, riempilo con una sfumatura usando CGGradientCreateWithColorComponents (). Uno degli argomenti di questa funzione è un array di 4 elementi di float (corrispondenti a R, G, B e alpha). Ho definito 2 array di colori, uno per ogni stato, e ho scelto quello appropriato in drawRect in base allo stato del pulsante.
daver

59

Ho un approccio diverso,

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

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

Non dimenticare di farlo #import <QuartzCore/QuartzCore.h>


2
Ben fatto. Ho scoperto che dovevo aggiungere unbtFind.layer.borderWidth = 1;
DefenestrationDay

Mi piace questa soluzione, ma al momento non posso utilizzarla. Ricevo un errore perché "CommonUIUtility" non può essere trovato. Google mi dà solo roba di eclissi, ma immagino che dovrebbe essere nel QuartzCore? Qualche idea?
Stephan

No, è una classe definita dall'utente per eseguire operazioni comuni dell'interfaccia utente nell'app. Scrivi il metodo imageFromColor nella tua classe.
karim

1
Puzza come un metodo di categoria su UIButton: setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB

3
È così stupido che siamo su iOS 7 e questo è ANCORA il modo più pulito per aggiungere un colore di sfondo
dmur

32

Presumo tu stia parlando di un UIButton con UIButtonTypeRoundedRect? Non puoi cambiare il colore di sfondo di quello. Quando provi a cambiare il suo colore di sfondo, stai piuttosto cambiando il colore del rettangolo su cui è disegnato il pulsante (che di solito è chiaro). Quindi ci sono due modi per andare. O si sottoclasse UIButton e si sovrascrive il suo -drawRect:metodo o si creano immagini per i diversi stati del pulsante (cosa che va benissimo).

Se imposti le immagini di sfondo in Interface Builder dovresti notare che IB non supporta l'impostazione delle immagini per tutti gli stati che il pulsante può avere, quindi ti consiglio di impostare le immagini nel codice in questo modo:

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

L'ultima riga mostra come impostare un'immagine per lo stato selezionato ed evidenziato (che è quello che IB non può impostare). Non hai bisogno delle immagini selezionate (riga 4 e 6) se il tuo pulsante non ha bisogno di uno stato selezionato.


Grazie per la spiegazione. Solo una domanda veloce. Se sovrascrivo il metodo drawrect immagino che ciò implicherebbe l'utilizzo di una libreria di disegni? Qualcosa da solo le linee di disegnare programmaticamente un rettangolo arrotondato e riempirlo con un colore?
doppiaggio

2
Ho appena fatto una breve query su Google per "iphone drawrect round corner" e ho trovato questo: iphonedevelopment.blogspot.com/2008/11/… Controlla il metodo drawrect per un esempio su come disegnare un round rect. Puoi usare CGContextSetFillColorWithColore CGContextFillPathper riempire il percorso disegnato da CGContextAddArcToPoint.
stigi

2
+50 per aver evidenziato il potenziale di mascheramento dei bit per gli stati di controllo, ad esempio: forState:(UIControlStateHighlighted | UIControlStateSelected)Saluti.
NSTJ

28

Un'altra possibilità:

  1. Crea un UIButton in Interface builder.
  2. Dagli un tipo "Personalizzato"
  3. Ora, in IB è possibile cambiare il colore di sfondo

Tuttavia, il pulsante è quadrato e non è quello che vogliamo. Crea un IBOutlet con un riferimento a questo pulsante e aggiungi quanto segue al metodo viewDidLoad:

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

Non dimenticare di importare QuartzCore.h


7
Perfetto, grazie! Non sono sicuro che sia a causa della versione iOS che sto utilizzando (5.1) ma setClipToBounds non era disponibile. Invece ho usato buttonOutlet.layer.masksToBounds = TRUE;
iforce2d

Quando aggiungo questo codice, mostra un rettangolo arrotondato, ma quando ci clicco sopra, il pulsante non inverte l'evidenziazione. Cosa sta succedendo?
Il

Il problema con questo approccio è che non è possibile impostare un colore di sfondo per lo stato evidenziato del pulsante.
ch3rryc0ke

17

Sottoclasse UIButton e sostituisce i metodi setHighlighted e 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];
}

Il mio metodo darkerShade è in una categoria UIColor come questa

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

7

pulsante UIB colorato

Se non desideri utilizzare le immagini e desideri che appaia esattamente come lo stile Rounded Rect, prova questo. Basta posizionare una UIView sul pulsante UIB, con una cornice identica e una maschera di ridimensionamento automatico, impostare l'alfa su 0,3 e impostare lo sfondo su un colore. Quindi utilizza lo snippet di seguito per ritagliare i bordi arrotondati dalla visualizzazione sovrapposta colorata. Inoltre, deseleziona la casella di controllo "Interazione utente abilitata" in IB su UIView per consentire agli eventi di tocco di ricadere sul pulsante UIB sotto.

Un effetto collaterale è che anche il tuo testo sarà colorato.

#import <QuartzCore/QuartzCore.h>

colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;

7

Un'altra possibilità (la migliore e più bella imho):

Crea un UISegmentedControl con 2 segmenti nel colore di sfondo richiesto in Interface Builder. Imposta il tipo su "bar". Quindi modificalo in modo che abbia un solo segmento. Il generatore di interfacce non accetta un segmento, quindi devi farlo a livello di programmazione.

Pertanto, crea un IBOutlet per questo pulsante e aggiungilo al viewDidLoad della tua vista:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Ora hai un bellissimo pulsante colorato lucido con il colore di sfondo specificato. Per le azioni, utilizza l'evento "valore modificato".

(L'ho trovato su http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ ). Grazie Chris!


5

Bene, sono sicuro al 99% per cento che non puoi semplicemente cambiare il colore di sfondo di un pulsante UIB. Invece devi andare a cambiare tu stesso le immagini di sfondo, il che penso sia un dolore. Sono stupito di aver dovuto farlo.

Se sbaglio o se c'è un modo migliore senza dover impostare immagini di sfondo per favore fatemelo sapere

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

5
Hai assolutamente ragione. È un dolore e qualcosa che dovrebbe richiedere alcuni minuti invece della seccatura di creare immagini. Inoltre, se il tuo pulsante è rotondo, è ancora più difficile farlo ... Un tale dolore.
Henley Chiu

2

Per suggerimento di @EthanB e @karim che crea un rettangolo riempito con il retro, ho appena creato una categoria per il pulsante UIB per ottenere questo risultato.

Basta inserire il codice della categoria: https://github.com/zmonteca/UIButton-PLColor

Uso:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

Facoltativo per gli stati da utilizzare:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected

2

Puoi anche aggiungere un CALayer al pulsante: puoi fare molte cose con questi, inclusa una sovrapposizione di colore, questo esempio utilizza uno strato di colore semplice che puoi anche graduare facilmente il colore. Tieni presente che i livelli aggiunti oscurano quelli sottostanti

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

}

Brillante!!!!!! Ma non poteva essere chiamato più volte sullo stesso pulsante. Potrebbe, ma nuovi livelli vengono aggiunti ancora e ancora.
Valeriy Van

@StanJames: le modifiche al codice dovrebbero essere suggerite da un commento (o, se appropriato, dalla tua risposta).
mafso

1

aggiungi un secondo target per il UIButtonfor UIControlEventTouchede cambia il UIButtoncolore di sfondo. Quindi cambiarlo di nuovo nel UIControlEventTouchUpInsidebersaglio;


1

Per pulsanti professionali e dall'aspetto gradevole, puoi controllare questo componente pulsante personalizzato . Puoi usarlo direttamente nelle viste e nelle tabelle o modificare il codice sorgente per adattarlo alle tue esigenze. Spero che questo ti aiuti.


1

Questo non è elegante come la sottoclasse UIButton, tuttavia se vuoi solo qualcosa di veloce - quello che ho fatto è stato creare un pulsante personalizzato, quindi un'immagine 1px per 1px con il colore che vorrei fosse il pulsante e impostare lo sfondo del pulsante a quell'immagine per lo stato evidenziato - funziona per le mie esigenze.


1

So che questo è stato chiesto molto tempo fa e ora c'è un nuovo UIButtonTypeSystem. Ma le domande più recenti vengono contrassegnate come duplicati di questa domanda, quindi ecco la mia risposta più recente nel contesto di un pulsante di sistema iOS 7, usa la .tintColorproprietà.

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

0

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

È possibile cambiare in questo modo o andare su Storyboard e cambiare lo sfondo nelle opzioni a destra.


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)

Questa sarebbe una risposta molto più utile se dicessi come invocare o utilizzare il codice che hai inserito. Va in un'estensione UIButton?
Michael Dautermann
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.