É possível alterar a cor de fundo de um UIButtons?

105

Este me deixou perplexo.

É possível mudar a cor de fundo de um UIButton no Cocoa para iPhone. Tentei definir a cor de fundo, mas só muda os cantos. setBackgroundColor:parece ser o único método disponível para tais coisas.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];
dublê
fonte
você pode consertar a imagem ou removê-la? kthx;)
stigi
o-0 hmmmm ....., a imagem estava boa, mas agora não aparecerá mais. Acabei de excluí-lo
dubbeat de
Esta é uma duplicata de stackoverflow.com/questions/372731/…
Brad Larson
Eu resolvo esse problema em minha postagem anterior, por favor, verifique o link [Alterar borda ou fundo de um UIButton dinamicamente] [1] [1]: stackoverflow.com/questions/9733213/…
IMORTAL
bom tutorial e código de amostra encontrados aqui cimgf.com/2010/01/28/…
Shamsudheen TK

Respostas:

160

Isso pode ser feito programaticamente, criando uma réplica:

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;

editar: é claro, você teria que #import <QuartzCore/QuartzCore.h>

editar: para todos os novos leitores, você também deve considerar algumas opções adicionadas como "outra possibilidade". para sua consideração.

Como esta é uma resposta antiga, recomendo fortemente a leitura dos comentários para solução de problemas

Stian Storrvik
fonte
É isso que o OP está procurando.
Steven,
4
doce! De todos os solns que encontrei, este é o que escolhi. Como um ponto de esclarecimento, fazer uma 'réplica' significa usar Quartz para desenhar um retângulo arredondado em um botão personalizado, em vez de usar um botão do tipo RoundedRect. A princípio, pensei que isso significasse fazer uma duplicata de um retângulo arredondado com uma cor diferente para simular a mudança da cor bg.
daver
1
Funcionou perfeitamente, melhor resposta para OP. Obrigado por compartilhar.
Bram
@daver: Esta resposta é tão popular que deve haver mérito que estou perdendo. Como mudar a cor de fundo de acordo com o estado? Presumivelmente, deve-se alterar explicitamente a cor de fundo toda vez que o estado muda. Meu botão é desabilitado ao pressionar até que um serviço da web responda. Devo mudar para cor de destaque na impressão e ter um temporizador mudando para cor desativada enquanto aguardo a resposta do ws? Se estou perdendo o ponto, alguém pode explicar. Obrigado Polly.
Polly
1
@Polly: Desculpe não ter visto seu comentário antes, mas se você ainda estiver interessado aqui está o que acabei fazendo: subclasse UIButton e substitua drawRect: para desenhar o retângulo arredondado usando alguns UIBezierPaths. Depois de desenhar, preencha com um gradiente usando CGGradientCreateWithColorComponents (). Um dos argumentos para esta função é uma matriz de 4 elementos de floats (correspondendo a R, G, B e alfa). Defndei 2 matrizes de cores, uma para cada estado, e escolhi a apropriada em drawRect com base no estado do botão.
daver
59

Eu tenho uma abordagem diferente,

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

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

Não se esqueça de #import <QuartzCore/QuartzCore.h>

karim
fonte
2
Agradável. Descobri que precisava adicionar umbtFind.layer.borderWidth = 1;
DefenestrationDay
Gosto desta solução, mas de momento não posso utilizá-la. Recebo um erro porque "CommonUIUtility" não pode ser encontrado. O Google apenas me dá coisas sobre eclipses, mas acho que deveria estar no QuartzCore? Alguma ideia?
Stephan,
Não, essa é uma classe definida pelo usuário para fazer coisas comuns de IU no aplicativo. Você escreve o método imageFromColor em sua própria classe.
karim
1
Cheira como um método categoria em UIButton: setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB de
3
É tão bobo que estamos no iOS 7 e esta AINDA é a maneira mais limpa de adicionar uma cor de fundo
dmur,
32

Suponho que você está falando sobre um UIButton com UIButtonTypeRoundedRect? Você não pode mudar a cor de fundo disso. Quando você tenta mudar a cor de fundo, está mudando a cor do retângulo no qual o botão é desenhado (que geralmente é claro). Portanto, há dois caminhos a percorrer. Ou você cria uma subclasse de UIButton e sobrescreve seu -drawRect:método, ou cria imagens para os diferentes estados do botão (o que é perfeitamente adequado ).

Se você definir as imagens de fundo no Interface Builder, deverá notar que o IB não oferece suporte à configuração de imagens para todos os estados que o botão pode ter, portanto, recomendo definir as imagens no código assim:

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

A última linha mostra como definir uma imagem para o estado selecionado e destacado (aquele que o IB não pode definir). Você não precisa das imagens selecionadas (linhas 4 e 6) se seu botão não precisa de um estado selecionado.

Stigi
fonte
Obrigado pela explicação. Só uma pergunta rápida. Se eu estiver sobrescrevendo o método drawrect, acho que isso envolveria o uso de uma biblioteca de desenhos. Algo sozinho, as linhas de desenhar programaticamente um retângulo arredondado e preenchê-lo com uma cor?
dubbeat de
2
Acabei de fazer uma breve consulta no Google por "iphone drawrect round corners" e encontrei o seguinte: iphonedevelopment.blogspot.com/2008/11/… Verifique o método drawrect para ver um exemplo de como desenhar um retângulo redondo. Você pode usar CGContextSetFillColorWithColore CGContextFillPathpara preencher o caminho desenhado por CGContextAddArcToPoint.
stigi
2
+50 para apontar o potencial de bitmasking para estados de controle, ou seja: forState:(UIControlStateHighlighted | UIControlStateSelected)Cheers.
NSTJ de
28

Outra possibilidade:

  1. Crie um UIButton no construtor de Interface.
  2. Dê a ele um tipo 'Custom'
  3. Agora, no IB é possível mudar a cor de fundo

No entanto, o botão é quadrado e não é isso que queremos. Crie um IBOutlet com uma referência a este botão e adicione o seguinte ao método viewDidLoad:

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

Não se esqueça de importar QuartzCore.h

wubbe
fonte
7
Perfeito, obrigado! Não tenho certeza se é por causa da versão do iOS que estou usando (5.1), mas setClipToBounds não estava disponível. Em vez disso, usei buttonOutlet.layer.masksToBounds = TRUE;
iforce2d
Quando adiciono este código, ele mostra um retângulo arredondado, mas quando clico nele, o botão não inverte o realce. O que está acontecendo?
Será em
O problema com esta abordagem é que você não pode definir uma cor de fundo para o estado realçado do botão.
ch3rryc0ke
17

Subclasse UIButton e substitua os métodos 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];
}

Meu método darkerShade está em uma categoria UIColor como esta

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

UIButton colorido

Se você não quiser usar imagens e quiser que elas fiquem exatamente como o estilo de retângulo arredondado, tente isto. Basta colocar um UIView sobre o UIButton, com um quadro idêntico e máscara de redimensionamento automático, definir o alfa para 0,3 e definir o fundo para uma cor. Em seguida, use o trecho abaixo para cortar as bordas arredondadas da visualização de sobreposição colorida. Além disso, desmarque a caixa de seleção 'Interação do usuário habilitada' no IB no UIView para permitir que os eventos de toque sejam transmitidos em cascata para o UIButton abaixo.

Um efeito colateral é que seu texto também ficará colorido.

#import <QuartzCore/QuartzCore.h>

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

Outra possibilidade (o melhor e mais belo imho):

Crie um UISegmentedControl com 2 segmentos na cor de fundo necessária no Interface Builder. Defina o tipo como 'bar'. Em seguida, mude para ter apenas um segmento. O construtor de interface não aceita um segmento, então você deve fazer isso programaticamente.

Portanto, crie um IBOutlet para este botão e adicione-o ao viewDidLoad de sua visualização:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Agora você tem um lindo botão colorido e brilhante com a cor de fundo especificada. Para ações, use o evento 'valor alterado'.

(Eu encontrei isso em http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ ). Obrigado Chris!

wubbe
fonte
5

Bem, tenho 99% de certeza de que você não pode simplesmente mudar a cor de fundo de um UIButton. Em vez disso, você mesmo tem que mudar as imagens de fundo, o que eu acho uma dor. Estou surpreso por ter que fazer isso.

Se eu estiver errado ou se houver uma maneira melhor sem ter que definir imagens de fundo, por favor me avise

[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];
dublê
fonte
5
Você está absolutamente correto. É uma dor e algo que deveria levar alguns minutos para fazer em vez do incômodo de criar imagens. Além disso, se o botão for redondo, fica ainda mais difícil de fazer também ... Que chatice.
Henley Chiu
2

Por sugestão de @EthanB e de @karim fazendo um retângulo preenchido, acabei de criar uma categoria para o UIButton conseguir isso.

Basta inserir o código da categoria: https://github.com/zmonteca/UIButton-PLColor

Uso:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

ForStates opcional para usar:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
zmonteca
fonte
2

Você também pode adicionar uma CALayer ao botão - você pode fazer muitas coisas com eles, incluindo uma sobreposição de cor, este exemplo usa uma camada de cor simples, você também pode graduar a cor facilmente. Esteja ciente de que as camadas adicionadas obscurecem as que estão embaixo

+(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
fonte
Brilhante!!!!!! Mas não pode ser chamado várias vezes contra o mesmo botão. Poderia, mas novas camadas são adicionadas novamente e novamente.
Valeriy Van
@StanJames: Edições no código devem ser sugeridas por um comentário (ou, se apropriado, por sua própria resposta).
mafso de
1

adicione um segundo alvo UIButtonpara UIControlEventTouchede mude a UIButtoncor de fundo. Em seguida, mude de volta para o UIControlEventTouchUpInsidealvo;

Shaun
fonte
1

Para botões profissionais e bonitos, você pode verificar este componente de botão personalizado . Você pode usá-lo diretamente em suas visualizações e tableviews ou modificar o código-fonte para fazê-lo atender às suas necessidades. Espero que isto ajude.

Ahmet Ardal
fonte
1

Isso não é tão elegante quanto subclassificar UIButton, no entanto, se você quiser algo rápido - o que fiz foi criar um botão personalizado, uma imagem de 1 x 1 pixel com a cor que eu gostaria que o botão tivesse e definir o plano de fundo do botão para aquela imagem para o estado destacado - funciona para minhas necessidades.

SMSidat
fonte
1

Eu sei que isso foi perguntado há muito tempo e agora há um novo UIButtonTypeSystem. Mas as perguntas mais recentes estão sendo marcadas como duplicatas desta pergunta, então aqui está minha resposta mais recente no contexto de um botão do sistema iOS 7, use a .tintColorpropriedade.

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

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

É possível mudar desta forma ou ir no Storyboard e mudar o fundo nas opções do lado direito.

Vinicius carvalho
fonte
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
fonte
Esta seria uma resposta muito mais útil se você dissesse como invocar ou fazer uso do código que você colocou lá. Ele vai para uma extensão UIButton?
Michael Dautermann