¿Es posible cambiar el color de fondo de un UIButtons?

105

Este me tiene perplejo.

¿Es posible cambiar el color de fondo de un UIButton en Cocoa para iPhone? Intenté configurar el color de fondo, pero solo cambia las esquinas. setBackgroundColor:parece ser el único método disponible para tales cosas.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];
dubbeat
fuente
¿Puedes arreglar la imagen o eliminarla? kthx;)
stigi
o-0 hmmmm ....., la imagen estaba bien, pero ahora no aparecerá más. Acabo de
borrarlo
Este es un duplicado de stackoverflow.com/questions/372731/…
Brad Larson
Resolví este problema en mi publicación anterior, verifique el enlace [Cambiar dinámicamente el borde o el fondo de un UIButton] [1] [1]: stackoverflow.com/questions/9733213/…
INMORTAL
buen tutorial y código de muestra que se encuentran aquí cimgf.com/2010/01/28/…
Shamsudheen TK

Respuestas:

160

Esto se puede hacer mediante programación haciendo una 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: por supuesto, tendrías que #import <QuartzCore/QuartzCore.h>

editar: para todos los lectores nuevos, también deben considerar algunas opciones agregadas como "otra posibilidad". para su consideración.

Como esta es una respuesta antigua, recomiendo encarecidamente leer los comentarios para solucionar problemas

Stian Storrvik
fuente
Esto es lo que busca el OP.
Steven
4
¡dulce! De todos los solns que encontré, este es el que elegí. Como punto de aclaración, hacer una 'réplica' significa usar Quartz para dibujar un rectángulo redondeado en un botón personalizado, en lugar de usar un botón tipo RoundedRect. Al principio pensé que significaba de alguna manera hacer un duplicado de un rectángulo redondeado con un color diferente para simular el cambio de color bg.
daver
1
Funcionó perfectamente, la mejor respuesta a OP. Gracias por compartir.
Bram
@daver: Esta respuesta es tan popular que debe tener un mérito que me falta. ¿Cómo se puede cambiar el color de fondo según el estado? Es de suponer que uno debe cambiar explícitamente el color de fondo cada vez que cambia el estado. Mi botón se desactiva al presionarlo hasta que un servicio web responde. ¿Debo cambiar para resaltar el color en la prensa y hacer que un temporizador cambie a color desactivado mientras espero que responda el ws? Si me estoy perdiendo el punto, ¿alguien puede explicarme? Gracias Polly.
Polly
1
@Polly: Lo siento, no vi tu comentario antes, pero si todavía estás interesado, esto es lo que terminé haciendo: subclase UIButton y anular drawRect: para dibujar el rectángulo redondeado usando algunos UIBezierPaths. Después de dibujar, rellénelo con un degradado usando CGGradientCreateWithColorComponents (). Uno de los argumentos de esta función es una matriz de 4 elementos de flotantes (correspondientes a R, G, B y alfa). Definí 2 matrices de colores, una para cada estado, y elegí la apropiada en drawRect según el estado del botón.
daver
59

Tengo un enfoque 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;

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

No te olvides de #import <QuartzCore/QuartzCore.h>

karim
fuente
2
Buena esa. Descubrí que tenía que agregar unbtFind.layer.borderWidth = 1;
DefenestrationDay
Me gusta esta solución, pero por el momento no puedo usarla. Recibo un error porque no se puede encontrar "CommonUIUtility". Google solo me da cosas de eclipse, pero supongo que debería estar en QuartzCore. ¿Algunas ideas?
Stephan
No, esa es una clase definida por el usuario para hacer cosas comunes de la interfaz de usuario en la aplicación. Escribe el método imageFromColor en su propia clase.
karim
1
Huele como un método categoría en UIButton: setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB
3
Es tan tonto que estemos en iOS 7 y TODAVÍA es la forma más limpia de agregar un color de fondo
dmur
32

Supongo que estás hablando de un UIButton con UIButtonTypeRoundedRect? No puedes cambiar el color de fondo de eso. Cuando intentas cambiar su color de fondo, estás cambiando el color del rectángulo en el que se dibuja el botón (que generalmente es claro). Así que hay dos caminos a seguir. O subclasifica UIButton y sobrescribe su -drawRect:método o crea imágenes para los diferentes estados de los botones (lo cual está perfectamente bien).

Si configura las imágenes de fondo en Interface Builder, debería notar que IB no admite la configuración de imágenes para todos los estados que puede tener el botón, por lo que recomiendo configurar las imágenes en un código como este:

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

La última línea muestra cómo configurar una imagen para el estado seleccionado y resaltado (ese es el que IB no puede configurar). No necesita las imágenes seleccionadas (líneas 4 y 6) si su botón no necesita un estado seleccionado.

Stigi
fuente
Gracias por la explicación. Solo una pregunta rápida. Si estoy sobrescribiendo el método drawrect, supongo que eso me involucraría usando una biblioteca de dibujos. ¿Algo solo las líneas de dibujar programáticamente un rectángulo redondeado y llenarlo con un color?
dubbeat
2
Acabo de hacer una breve consulta en Google para "iphone drawrect round esquinas" y encontré esto: iphonedevelopment.blogspot.com/2008/11/… Verifique el método drawrect para ver un ejemplo de cómo dibujar un rectángulo redondo. Puede utilizar CGContextSetFillColorWithColory CGContextFillPathpara rellenar el camino dibujado por CGContextAddArcToPoint.
stigi
2
+50 por señalar el potencial de enmascaramiento de bits para los estados de control, es decir: forState:(UIControlStateHighlighted | UIControlStateSelected)Saludos.
NSTJ
28

Otra posibilidad:

  1. Cree un UIButton en el constructor de interfaces.
  2. Dale un tipo 'Personalizado'
  3. Ahora, en IB es posible cambiar el color de fondo

Sin embargo, el botón es cuadrado y eso no es lo que queremos. Cree un IBOutlet con una referencia a este botón y agregue lo siguiente al método viewDidLoad:

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

No olvide importar QuartzCore.h

wubbe
fuente
7
¡Perfecto, gracias! No estoy seguro de si es por la versión de iOS que estoy usando (5.1) pero setClipToBounds no estaba disponible. En su lugar, usé buttonOutlet.layer.masksToBounds = TRUE;
iforce2d
Cuando agrego este código, muestra un rectángulo redondeado, pero cuando hago clic en él, el botón no se resalta en reversa. Que esta pasando?
Será
El problema con este enfoque es que no puede establecer un color de fondo para el estado resaltado del botón.
ch3rryc0ke
17

Subclase UIButton y anular los métodos setHighlight y 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];
}

Mi método darkerShade está en una categoría 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
fuente
7

UIButton de color

Si no desea utilizar imágenes y desea que se vea exactamente como el estilo Rect redondeado, intente esto. Simplemente coloque una UIView sobre el UIButton, con un marco idéntico y una máscara de cambio de tamaño automático, configure el alfa en 0.3 y configure el fondo en un color. Luego, use el fragmento de abajo para recortar los bordes redondeados de la vista de superposición de colores. Además, desmarque la casilla de verificación 'Interacción del usuario habilitada' en IB en UIView para permitir que los eventos táctiles caigan en cascada hasta el botón UIB debajo.

Un efecto secundario es que su texto también se coloreará.

#import <QuartzCore/QuartzCore.h>

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

Otra posibilidad (la mejor y más hermosa en mi humilde opinión):

Cree un UISegmentedControl con 2 segmentos en el color de fondo requerido en Interface Builder. Establezca el tipo en 'barra'. Luego, cámbielo para que tenga solo un segmento. El generador de interfaces no acepta un segmento, por lo que debe hacerlo mediante programación.

Por lo tanto, cree un IBOutlet para este botón y agréguelo a viewDidLoad de su vista:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Ahora tiene un hermoso botón de color brillante con el color de fondo especificado. Para las acciones, use el evento 'valor cambiado'.

(Encontré esto en http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ ). Gracias Chris!

wubbe
fuente
5

Bueno, estoy 99% seguro de que no puedes simplemente cambiar el color de fondo de un botón UIB. En su lugar, tienes que ir y cambiar las imágenes de fondo tú mismo, lo cual creo que es un fastidio. Me sorprende tener que hacer esto.

Si me equivoco o si hay una mejor manera sin tener que configurar imágenes de fondo, hágamelo saber.

[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
fuente
5
Estás absolutamente en lo correcto. Es una molestia y algo que debería tomar unos minutos para hacer en lugar de la molestia de crear imágenes. Además, si su botón es redondo, también lo hace aún más difícil de hacer ... Qué molestia.
Henley Chiu
2

Según la sugerencia de @EthanB y @karim haciendo un rectángulo relleno hacia atrás, acabo de crear una categoría para que el UIButton logre esto.

Simplemente ingrese el código de categoría: https://github.com/zmonteca/UIButton-PLColor

Uso:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

Opcional para que los Estados lo utilicen:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
zmonteca
fuente
2

También puede agregar un CALayer al botón; puede hacer muchas cosas con estos, incluida una superposición de color, este ejemplo usa una capa de color simple y también puede graduar fácilmente el color. Tenga en cuenta que las capas añadidas oscurecen las que están debajo

+(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
fuente
¡¡¡¡¡¡Brillante!!!!!! Pero no se pudo llamar varias veces contra el mismo botón. Podría, pero se agregan nuevas capas una y otra vez.
Valeriy Van
@StanJames: Las ediciones al código deben ser sugeridas por un comentario (o, si corresponde, por su propia respuesta).
mafso
1

añadir un segundo objetivo para el UIButtonpara UIControlEventTouchedy cambiar el UIButtoncolor de fondo. Luego cámbielo nuevamente en el UIControlEventTouchUpInsideobjetivo;

Shaun
fuente
1

Para botones profesionales y atractivos, puede comprobar este componente de botón personalizado . Puede usarlo directamente en sus vistas y vistas de tabla o modificar el código fuente para adaptarlo a sus necesidades. Espero que esto ayude.

Ahmet Ardal
fuente
1

Esto no es tan elegante como subclasificar UIButton, sin embargo, si solo quieres algo rápido, lo que hice fue crear un botón personalizado, luego una imagen de 1 px por 1 px con el color que me gustaría que tuviera el botón y establecer el fondo del botón a esa imagen para el estado resaltado - funciona para mis necesidades.

SMSidat
fuente
1

Sé que esto se preguntó hace mucho tiempo y ahora hay un nuevo UIButtonTypeSystem. Pero las preguntas más nuevas se marcan como duplicados de esta pregunta, así que aquí está mi respuesta más nueva en el contexto de un botón del sistema iOS 7, use la .tintColorpropiedad.

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

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

Es posible cambiar de esta manera o ir al Storyboard y cambiar el fondo en las opciones del lado derecho.

Vinicius Carvalho
fuente
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
fuente
Esta sería una respuesta mucho más útil si dijera cómo invocar o hacer uso del código que ha colocado allí. ¿Entra en una extensión UIButton?
Michael Dautermann