Est-il possible de changer une couleur d'arrière-plan UIButtons?

105

Celui-ci m'a perplexe.

Est-il possible du tout de changer la couleur de fond d'un UIButton dans Cocoa pour iPhone. J'ai essayé de définir la couleur d'arrière-plan mais cela ne change que les coins. setBackgroundColor:semble être la seule méthode disponible pour de telles choses.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];
dubbeat
la source
pouvez-vous corriger l'image ou la supprimer? kthx;)
stigi
o-0 hmmmm ....., l'image était correcte mais maintenant elle n'apparaîtra plus. Je viens de le supprimer
dubbeat
Ceci est un double de stackoverflow.com/questions/372731/…
Brad Larson
Je résous ce problème dans mon post précédent s'il vous plaît vérifier le lien [Changer dynamiquement la bordure ou l'arrière-plan d'un UIButton] [1] [1]: stackoverflow.com/questions/9733213/…
IMMORTAL
bon tutoriel et exemple de code trouvé ici cimgf.com/2010/01/28/…
Shamsudheen TK

Réponses:

160

Cela peut être fait par programme en créant une réplique:

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;

modifier: bien sûr, il faudrait #import <QuartzCore/QuartzCore.h>

edit: à tous les nouveaux lecteurs, vous devriez également considérer quelques options ajoutées comme "une autre possibilité". pour votre considération.

Comme il s'agit d'une ancienne réponse, je recommande fortement de lire les commentaires pour le dépannage

Stian Storrvik
la source
C'est ce que recherche l'OP.
Steven
4
doux! De toutes les solns que j'ai trouvées, c'est celle avec laquelle je suis allé. Pour clarifier, faire une «réplique» signifie utiliser Quartz pour dessiner un rectangle arrondi dans un bouton personnalisé, plutôt que d'utiliser un bouton de type RoundedRect. Au début, je pensais que cela signifiait en quelque sorte faire une duplication d'un rect arrondi avec une couleur différente pour simuler le changement de la couleur bg.
daver
1
A parfaitement fonctionné, meilleure réponse à OP. Merci d'avoir partagé.
Bram
@daver: Cette réponse est si populaire qu'elle doit avoir du mérite qui me manque. Comment changer la couleur de fond en fonction de l'état? Vraisemblablement, il faut changer explicitement la couleur d'arrière-plan chaque fois que l'état change. Mon bouton est désactivé lorsque vous appuyez sur jusqu'à ce qu'un service Web réponde. Dois-je changer pour mettre la couleur en surbrillance sur la presse et faire changer la minuterie en couleur désactivée en attendant que le ws réponde? Si je manque le point, quelqu'un peut-il expliquer. Merci Polly.
Polly
1
@Polly: Désolé de ne pas avoir vu votre commentaire plus tôt, mais si vous êtes toujours intéressé, voici ce que j'ai fini par faire: sous-classe UIButton et surcharger drawRect: pour dessiner le rect arrondi en utilisant certains UIBezierPaths. Après avoir dessiné, remplissez-le d'un dégradé à l'aide de CGGradientCreateWithColorComponents (). L'un des arguments de cette fonction est un tableau de 4 éléments flottants (correspondant à R, G, B et alpha). J'ai défini 2 tableaux de couleurs, un pour chaque état, et j'ai choisi celui qui convient dans drawRect en fonction de l'état du bouton.
daver
59

J'ai une approche différente,

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

De 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'oubliez pas de #import <QuartzCore/QuartzCore.h>

Karim
la source
2
Joli. J'ai trouvé que je devais ajouter unbtFind.layer.borderWidth = 1;
DefenestrationDay
J'aime cette solution, mais pour le moment je ne peux pas l'utiliser. J'obtiens une erreur, car "CommonUIUtility" est introuvable. Google me donne juste des trucs d'éclipse, mais je suppose que ça devrait être dans QuartzCore? Des idées?
Stephan
Non, il s'agit d'une classe définie par l'utilisateur pour effectuer des tâches d'interface utilisateur courantes dans l'application. Vous écrivez la méthode imageFromColor dans votre propre classe.
karim
1
Ça sent comme une méthode de catégorie sur UIButton: setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB
3
C'est tellement idiot que nous sommes sur iOS 7 et c'est TOUJOURS le moyen le plus propre d'ajouter une couleur d'arrière-plan
dmur
32

Je suppose que vous parlez d'un UIButton avec UIButtonTypeRoundedRect? Vous ne pouvez pas changer la couleur d'arrière-plan de cela. Lorsque vous essayez de changer sa couleur d'arrière-plan, vous changez plutôt la couleur du rectangle sur lequel le bouton est dessiné (ce qui est généralement clair). Il y a donc deux façons de procéder. Soit vous sous-classez UIButton et écrasez sa -drawRect:méthode, soit vous créez des images pour les différents états de bouton (ce qui est parfaitement bien à faire).

Si vous définissez les images d'arrière-plan dans Interface Builder, vous devriez remarquer que IB ne prend pas en charge la configuration des images pour tous les états que le bouton peut avoir, je vous recommande donc de définir les images dans un code comme celui-ci:

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 dernière ligne montre comment définir une image pour l'état sélectionné et mis en surbrillance (c'est celui que IB ne peut pas définir). Vous n'avez pas besoin des images sélectionnées (lignes 4 et 6) si vous n'avez pas besoin d'un état sélectionné.

stigi
la source
Merci pour l'explication. Juste une petite question. Si j'écrase la méthode drawrect, je suppose que cela m'impliquerait d'utiliser une bibliothèque de dessins? Quelque chose seul les lignes de dessiner par programme un rectangle arrondi et de le remplir d'une couleur?
dubbeat
2
Je viens de faire une courte requête google pour "iphone drawrect round coins" et j'ai trouvé ceci: iphonedevelopment.blogspot.com/2008/11/… Vérifiez la méthode drawrect pour un exemple comment dessiner un rect rond. Vous pouvez utiliser CGContextSetFillColorWithColoret CGContextFillPathpour remplir le chemin tracé par CGContextAddArcToPoint.
stigi
2
+50 pour souligner le potentiel de masquage de bits pour les états de contrôle, c'est-à-dire: forState:(UIControlStateHighlighted | UIControlStateSelected)Cheers.
NSTJ
28

Une autre possibilité:

  1. Créez un UIButton dans le générateur d'interface.
  2. Donnez-lui un type "Personnalisé"
  3. Maintenant, dans IB, il est possible de changer la couleur de fond

Cependant, le bouton est carré et ce n'est pas ce que nous voulons. Créez un IBOutlet avec une référence à ce bouton et ajoutez ce qui suit à la méthode viewDidLoad:

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

N'oubliez pas d'importer QuartzCore.h

wubbe
la source
7
Parfait, merci! Je ne sais pas si c'est à cause de la version iOS que j'utilise (5.1) mais setClipToBounds n'était pas disponible. Au lieu de cela, j'ai utilisé buttonOutlet.layer.masksToBounds = TRUE;
iforce2d
Lorsque j'ajoute ce code, il montre un rect arrondi, mais lorsque je clique dessus, le bouton n'inverse pas la surbrillance. Que se passe-t-il?
Sera le
Le problème avec cette approche est que vous ne pouvez pas définir une couleur d'arrière-plan pour l'état en surbrillance du bouton.
ch3rryc0ke
17

Sous-classe UIButton et override Méthodes setHighlighted et 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];
}

Ma méthode darkerShade est dans une catégorie UIColor comme celle-ci

-(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
la source
7

UIButton coloré

Si vous ne souhaitez pas utiliser d'images et que vous souhaitez qu'elles ressemblent exactement au style Rounded Rect, essayez ceci. Placez simplement un UIView sur l'UIButton, avec un cadre et un masque de redimensionnement automatique identiques, définissez l'alpha sur 0,3 et définissez l'arrière-plan sur une couleur. Utilisez ensuite l'extrait ci-dessous pour découper les bords arrondis de la vue de superposition colorée. Décochez également la case `` User Interaction Enabled '' dans IB sur l'UIView pour permettre aux événements tactiles de se dérouler en cascade vers l'UIButton en dessous.

Un effet secondaire est que votre texte sera également colorisé.

#import <QuartzCore/QuartzCore.h>

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

Une autre possibilité (la meilleure et la plus belle à mon humble avis):

Créez un UISegmentedControl avec 2 segments dans la couleur d'arrière-plan requise dans Interface Builder. Définissez le type sur «bar». Ensuite, changez-le pour n'avoir qu'un seul segment. Le générateur d'interface n'accepte pas un segment, vous devez donc le faire par programme.

Par conséquent, créez un IBOutlet pour ce bouton et ajoutez-le au viewDidLoad de votre vue:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Vous avez maintenant un beau bouton brillant et coloré avec la couleur d'arrière-plan spécifiée. Pour les actions, utilisez l'événement «valeur modifiée».

(J'ai trouvé ceci sur http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ ). Merci Chris!

wubbe
la source
5

Eh bien, je suis à 99% sûr que vous ne pouvez pas simplement changer la couleur d'arrière-plan d'un UIButton. Au lieu de cela, vous devez changer vous-même les images d'arrière-plan, ce qui, à mon avis, est pénible. Je suis étonné de devoir faire ça.

Si je me trompe ou s'il existe un meilleur moyen sans avoir à définir des images d'arrière-plan, veuillez me le faire savoir

[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
la source
5
Vous avez absolument raison. C'est une douleur, et quelque chose qui devrait prendre quelques minutes à faire au lieu des tracas de créer des images. De plus, si votre bouton est rond, cela le rend encore plus difficile à faire aussi ... Une telle douleur.
Henley Chiu du
2

Par suggestion @EthanB et @karim faisant un rectangle rempli à l'arrière, je viens de créer une catégorie pour l'UIButton pour y parvenir.

Il suffit de déposer le code de catégorie: https://github.com/zmonteca/UIButton-PLColor

Usage:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

Facultatif pour les États à utiliser:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected
Zmonteca
la source
2

Vous pouvez également ajouter un CALayer au bouton - vous pouvez faire beaucoup de choses avec ceux-ci, y compris une superposition de couleur, cet exemple utilise un calque de couleur unie, vous pouvez également facilement graduer la couleur. Soyez conscient que les couches ajoutées obscurcissent celles en dessous

+(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
la source
Brillant!!!!!! Mais ne pouvait pas être appelé plusieurs fois contre le même bouton. Pourrait, mais de nouvelles couches sont ajoutées encore et encore.
Valeriy Van
@StanJames: Les modifications du code doivent être suggérées par un commentaire (ou, le cas échéant, par votre propre réponse).
mafso
1

ajoutez une deuxième cible pour le UIButtonpour UIControlEventTouchedet changez la UIButtoncouleur d'arrière - plan. Puis changez-le dans la UIControlEventTouchUpInsidecible;

Shaun
la source
1

Pour des boutons professionnels et agréables, vous pouvez vérifier ce composant de bouton personnalisé . Vous pouvez l'utiliser directement dans vos vues et tables vues ou modifier le code source pour qu'il réponde à vos besoins. J'espère que cela t'aides.

Ahmet Ardal
la source
1

Ce n'est pas aussi élégant que le sous-classement d'UIButton, mais si vous voulez juste quelque chose de rapide - ce que j'ai fait a été de créer un bouton personnalisé, puis une image 1px par 1px avec la couleur que je voudrais que le bouton soit, et définir l'arrière-plan du bouton à cette image pour l'état en surbrillance - fonctionne pour mes besoins.

SMSidat
la source
1

Je sais que cela a été demandé il y a longtemps et qu'il y a maintenant un nouveau UIButtonTypeSystem. Mais les nouvelles questions sont marquées comme des doublons de cette question, alors voici ma nouvelle réponse dans le contexte d'un bouton système iOS 7, utilisez la .tintColorpropriété.

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

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

Il est possible de changer de cette façon ou d'aller sur Storyboard et de changer l'arrière-plan sur les options du côté droit.

Vinicius Carvalho
la source
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
la source
Ce serait une réponse beaucoup plus utile si vous disiez comment invoquer ou utiliser le code que vous avez mis là-haut. Va-t-il dans une extension UIButton?
Michael Dautermann