Comment définir une couleur d'arrière-plan personnalisée pour un bouton?
Interface Builder ne semble pas avoir d'interface pour le faire.
Est-ce seulement disponible par programme? Si oui, pouvez-vous donner un exemple, s'il vous plaît?
J'ai lu votre question pour require (comme je le fais) un programmatique moyen de régler la couleur des boutons. C'est une omission flagrante de UIKit, et je ne pouvais pas faire fonctionner le UIGlassButton sans papiers.
J'ai résolu ceci avec un seul segment UISegmentedControl
, ce qui vous permet de définir la tintColor
:
UISegmentedControl * btn = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:name]];
btn.momentary = YES;
btn.segmentedControlStyle = UISegmentedControlStyleBar;
btn.tintColor = color;
[btn addTarget:self action:@selector(action:) forControlEvents:UIControlEventValueChanged];
Notez que les propriétés momentary
et segmentedControlStyle
sont importantes et qu’une image peut être utilisée à la place du nom NSString *
.
Une image extensible avec des embouts fonctionne parfaitement si vous pouvez utiliser un ensemble fini d’images en boîte, mais cela ne correspond pas à l’exigence! Par exemple.,
buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:26 topCapHeight:16];
J'ai trouvé que je devais utiliser une image extensible pour accomplir cela. L'exemple UICatalog d'Apple comporte un ou plusieurs boutons colorés dessinés de cette façon. Vous pouvez utiliser leur modèle d'image et le recolorer pour l'adapter à vos besoins en matière de boutons.
Je ne suis pas sûr de pouvoir le faire dans Interface Builder, mais j'ai pu créer un bouton et utiliser une image pour son contenu à l'aide du code suivant:
downloadButton = [[UIButton alloc] initWithFrame:CGRectMake(36, 212, 247, 37)];
downloadButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
downloadButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[downloadButton setTitle:NSLocalizedStringFromTable(@"Download", @"Localized", nil) forState:UIControlStateNormal];
[downloadButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[downloadButton setFont:[UIFont boldSystemFontOfSize:14.0]];
UIImage *newImage = [[UIImage imageNamed:@"greenButton.png"] stretchableImageWithLeftCapWidth:12.0f topCapHeight:0.0f];
[downloadButton setBackgroundImage:newImage forState:UIControlStateNormal];
[downloadButton addTarget:self action:@selector(downloadNewItem) forControlEvents:UIControlEventTouchDown];
downloadButton.backgroundColor = [UIColor clearColor];
[downloadDisplayView addSubview:downloadButton];
Définir la couleur d'arrière-plan de la vue pour un bouton rectangle arrondi ne changera pas la couleur d'arrière-plan du bouton. Essayez de personnaliser le bouton (le premier menu déroulant de l'inspecteur), puis de définir la couleur d'arrière-plan. Vous obtiendrez l'effet désiré :)
Il semble que la couleur des boutons soit toujours un problème. La catégorie suivante définit l'image d'arrière-plan d'un bouton de manière complètement programmée via une méthode d'instance utilisant un paramètre UIColor. Il n'est pas nécessaire de créer des fichiers backgroundimage de bouton. Il préserve le comportement des boutons basé sur UIControlState. Et ça garde les coins arrondis.
Le fichier d'en-tête UIButton + ColoredBackground.h
#import <UIKit/UIKit.h>
@interface UIButton (ColoredBackground)
- (void)setBackgroundImageByColor:(UIColor *)backgroundColor forState:(UIControlState)state;
@end
et le contenu de UIButton + ColoredBackground.m
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIButton (ColoredBackground)
- (void)setBackgroundImageByColor:(UIColor *)backgroundColor forState:(UIControlState)state{
// tcv - temporary colored view
UIView *tcv = [[UIView alloc] initWithFrame:self.frame];
[tcv setBackgroundColor:backgroundColor];
// set up a graphics context of button's size
CGSize gcSize = tcv.frame.size;
UIGraphicsBeginImageContext(gcSize);
// add tcv's layer to context
[tcv.layer renderInContext:UIGraphicsGetCurrentContext()];
// create background image now
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// set image as button's background image for the given state
[self setBackgroundImage:image forState:state];
UIGraphicsEndImageContext();
// ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = 8.0;
[tcv release];
}
@end
La nouvelle méthode est juste appelée sur chaque instance UIButton comme:
[myButton setBackgroundImageByColor:[UIColor greenColor] forState:UIControlStateNormal];
http://github.com/dermdaly/ButtonMaker
Vous pouvez générer une image UIbutton à l'aide de cette application ... et la définir comme image d'arrière-plan de votre bouton.
Définissez le type de bouton sur "Personnalisé" dans la palette des attributs de bouton. Cela vous donnera un bouton carré avec la couleur que vous avez choisie pour le fond.
Si vous voulez un bouton qui ressemble plus à un bouton traditionnel, mais qui a une couleur différente, vous devrez vous connecter à un logiciel d'édition d'images et le créer (j'utilise Photoshop pour les boutons personnalisés).
Ce lien fournit une solution élégante à votre problème ... http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/
Pour garder le bouton arrondi, qu’en est-il de l’utilisation de
view.layer.cornerRadius = 8;
décrit ici
j'ai un peu modifié la version de code de @Patch. Le problème pour moi était que l'ancienne version étendait le rayon de coin de manière sale lors du passage du mode portrait au mode paysage. J'ai donc fait en sorte que cette version utilise la méthode stretchableImageWithLeftCapWidth: topCapHeight.
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
#define kCornerRadius 8.0f
#define kStrokeColor [UIColor blackColor]
#define kStrokeWidth 1.0f
@implementation UIButton (ColoredBackground)
- (void)setBackgroundImageByColor:(UIColor *)backgroundColor forState:(UIControlState)state{
CGSize gcSize = CGSizeMake(2*kCornerRadius +1, self.bounds.size.height);
UIGraphicsBeginImageContext(gcSize);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeOverlay);
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
UIColor *gradientStart = [UIColor colorWithRed:0.80 green:0.80 blue:0.80 alpha:0.2];
UIColor * gradientEnd = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.2];
NSArray *colors = [NSArray arrayWithObjects:(id)gradientStart.CGColor, (id)gradientEnd.CGColor, nil];
CGFloat locations[2] = { 0.0f, 1.0f };
CGGradientRef _gradient = CGGradientCreateWithColors(rgb, (__bridge CFArrayRef)colors, locations);
CGColorSpaceRelease(rgb);
CGContextDrawLinearGradient(UIGraphicsGetCurrentContext(), _gradient, CGPointMake(0.0, kStrokeWidth), CGPointMake(0.0, self.bounds.size.height-kStrokeWidth), 0);
UIBezierPath *outsideEdge = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0, 0.0, gcSize.width, gcSize.height) cornerRadius:kCornerRadius];
[backgroundColor setFill];
[kStrokeColor setStroke];
outsideEdge.lineWidth = kStrokeWidth;
[outsideEdge stroke];
[outsideEdge fill];
// Create the background image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set image as button's background image (stretchable) for the given state
[self setBackgroundImage:[image stretchableImageWithLeftCapWidth:kCornerRadius topCapHeight:0.0] forState:state];
// Ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = kCornerRadius;
}
@end
L'utilisation n'a pas changé. Cela semble plus clair maintenant sur les bords, et j'ai également ajouté un dégradé pour faire plus de plastique. mais vous pouvez aussi le supprimer.
Voici une variante de la solution de @ user200212 (http://stackoverflow.com/a/8547424). Il utilise la classe UIBezierCurve
pour remplir le bouton et dessiner une bordure noire de 1px autour de lui:
UIButton + ColoredBackground.h
// UIButton+ColoredBackground.h
#import <UIKit/UIKit.h>
@interface UIButton (ColoredBackground)
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
+ (UIColor *) silverColor;
@end
UIButton + ColoredBackground.m
// UIButton+ColoredBackground.m
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIButton (UIButton_ColoredBackground)
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state{
CGSize gcSize = self.bounds.size;
UIGraphicsBeginImageContext(gcSize);
// Create a Bezier Path around the button, and fill it with the background color
UIBezierPath *outsideEdge = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:8.0f];
[backgroundColor setFill];
[[UIColor blackColor] setStroke];
outsideEdge.lineWidth = 1.0;
[outsideEdge fill];
[outsideEdge stroke];
// Create the background image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set image as button's background image for the given state
[self setBackgroundImage:image forState:state];
// Ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = 8.0;
}
@end
Usage:
[myButton setBackgroundImageByColor:[UIColor greenColor] forState:UIControlStateNormal];
La solution de Tim James (un contrôle segmenté à segment unique) a fonctionné pour moi lorsque je voulais un simple bouton «Enregistrer» avec un fond dégradé bleu décent. J'ai simplement créé un contrôle à 2 segments dans le nib, configuré le premier segment comme je le voulais, puis supprimé par programme le second segment sous -viewWillAppear à l'aide de [mySegmentedControl removeSegmentAtIndex: 1 animé: NO] . devait être actif (coché) pour le premier segment de la commande segmenté et que 'Selected' n'était activé pour aucun des deux segments. 'Valeur modifiée' est l'action de connexion du contrôle segmenté.
je l'ai fait comme suit pour créer un bouton comme le bouton de suppression du système comme dans uitableview
UIButton *h=[[UIButton alloc]init];
[[h layer] setCornerRadius:8.0f];
[[h layer] setMasksToBounds:YES];
[[h layer] setBorderWidth:1.0f];
CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
[gradientLayer setBounds:[h bounds]];
[gradientLayer setPosition:CGPointMake([h bounds].size.width/2, [h bounds].size.height/2)];
[gradientLayer setColors:[NSArray arrayWithObjects:
(id)[[UIColor darkGrayColor]CGColor],(id)[[UIColor blackColor] CGColor], nil]];
[[h layer] insertSublayer:gradientLayer atIndex:0];
libérez tous les objets et importez QuartzCore/QuartzCore.h et ajoutez ce cadre à votre projet.
Voici une application gratuite que j'ai créée qui crée des images UIGlassButton. Définissez le type de bouton sur personnalisé. http://iTunes.Apple.com/us/app/uibutton-builder/id408204223?mt=8
J'ai résolu ce problème en créant mon propre bouton dans Fireworks. J'ai dessiné un rectangle arrondi de la taille souhaitée, avec la couleur de remplissage et la couleur de bordure souhaitées. Découpez la toile et enregistrez-la au format PNG. Dans XCode, ajoutez le fichier au dossier Ressources. Vous pouvez utiliser un bouton Personnalisé dans Interface Builder et spécifier l'image en tant que PNG. Il le redimensionnera au besoin, mettra le texte en haut, etc. La courbe des coins peut se déformer si vous devez le redimensionner beaucoup par rapport à l'original.
J'ai donc trouvé une solution incroyablement simple en utilisant les catégories ..__ (Si simple que je pense que je dois faire quelque chose de méchant, mais je ne le vois pas!)
Définir une catégorie (si vous ne savez pas ce que c'est, en résumé: c'est un moyen "d'étendre" une classe de façon minimale, c'est-à-dire d'ajouter des méthodes à une classe mais pas de propriétés) pour UIButton et de créer une méthode setBackgroundColor "qui appelle la méthode setBackgroundColor de la super classe '(UIControl) de UIButton.
@implementation UIButton (coloredBackgroundButton)
-(void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:backgroundColor];
}
Où que vous utilisiez les boutons UIB, tant que vous importez le fichier d’en-tête dans lequel cette catégorie est déclarée, dans ce cas,
#import "coloredBackgroundButton.h"
vous pouvez appeler setBackgroundColor sur eux.
keremk avait raison lorsqu'il a dit de changer la couleur d'arrière-plan de la vue lorsque vous avez cliqué sur le bouton et entré dans l'inspecteur. Cela change les petits coins dans la couleur que vous avez choisie.
Essayez ceci si vous ne voulez pas utiliser d'images et que vous voulez que cela ressemble exactement au style Rounded Rect. 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 le fond comme couleur. Utilisez ensuite l'extrait de code ci-dessous pour couper les bords arrondis de la vue superposée colorée. Décochez également la case "Interaction utilisateur activée" dans IB sur UIView pour permettre aux événements tactiles d’être transmis en cascade au-dessous de UIButton.
Un effet secondaire est que votre texte sera également colorisé.
#import <QuartzCore/QuartzCore.h>
colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;
Construire plus loin sur @ Denny1989 J'ai résolu un problème avec les erreurs (contexte non valide 0x0) lors de la configuration du bouton dans viewDidLoad. Le bouton doit être disposé avant de prendre une taille et ne peut donc être utilisé qu'après l'affichage de la vue. Cette catégorie ajoute une couleur pour UIControlStateNormal. Si d'autres états de contrôle sont nécessaires pour votre application, vous devez les ajouter de la même manière à la catégorie.
// UIButton+ColoredBackground.h
#import <UIKit/UIKit.h>
@interface UIButton (ColoredBackground)
@property (nonatomic, retain) UIColor *buttonColorNormal;
@property (nonatomic, retain) NSNumber *madeBackgroundImages;
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
- (void)drawRect:(CGRect)rect;
- (void)awakeFromNib;
@end
et
// UIButton+ColoredBackground.m
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
#define kCornerRadius 8.0f
#define kStrokeColor [UIColor darkGrayColor]
#define kStrokeWidth 1.0f
@implementation UIButton (ColoredBackground)
static char UIB_ButtonColorNormal_KEY;
static char UIB_MadeBackgroundImages_KEY;
@dynamic buttonColorNormal;
-(void)setButtonColorNormal:(NSObject *)buttonColorNormal
{
objc_setAssociatedObject(self, &UIB_ButtonColorNormal_KEY, buttonColorNormal, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSObject*)buttonColorNormal
{
return (NSObject*)objc_getAssociatedObject(self, &UIB_ButtonColorNormal_KEY);
}
@dynamic madeBackgroundImages;
-(void)setMadeBackgroundImages:(NSObject *)madeBackgroundImages
{
objc_setAssociatedObject(self, &UIB_MadeBackgroundImages_KEY, madeBackgroundImages, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSObject*)madeBackgroundImages
{
return (NSObject*)objc_getAssociatedObject(self, &UIB_MadeBackgroundImages_KEY);
}
- (void)awakeFromNib {
[self setMadeBackgroundImages:[NSNumber numberWithBool:FALSE]];
[super awakeFromNib];
}
- (void)drawRect:(CGRect)rect {
// if background images were not created from color do so here
// if self.buttonColorNormal is not set behaves like normal button
if ((self.buttonColorNormal)&&(![[self madeBackgroundImages] boolValue])) {
[self setBackgroundColor:[self buttonColorNormal] forState:UIControlStateNormal];
[self setMadeBackgroundImages:[NSNumber numberWithBool:TRUE]];
}
[super drawRect:rect];
}
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state {
gcSize = CGSizeMake(2*kCornerRadius +1, self.bounds.size.height);
UIGraphicsBeginImageContext(gcSize);
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
UIColor *gradientStart = [UIColor colorWithRed:0.80 green:0.80 blue:0.80 alpha:0.2];
UIColor * gradientEnd = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
NSArray *colors = [NSArray arrayWithObjects:(id)gradientStart.CGColor, (id)gradientEnd.CGColor, nil];
CGFloat locations[2] = { 0.0f, 1.0f };
CGGradientRef _gradient = CGGradientCreateWithColors(rgb, (__bridge CFArrayRef)colors, locations);
CGColorSpaceRelease(rgb);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeOverlay);
CGContextDrawLinearGradient(UIGraphicsGetCurrentContext(), _gradient, CGPointMake(0.0, kStrokeWidth), CGPointMake(0.0, self.bounds.size.height-kStrokeWidth), 0);
UIBezierPath *outsideEdge = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0, 0.0, gcSize.width, gcSize.height) cornerRadius:kCornerRadius];
[backgroundColor setFill];
[kStrokeColor setStroke];
outsideEdge.lineWidth = kStrokeWidth;
[outsideEdge stroke];
[outsideEdge fill];
CFRelease(_gradient);
// Create the background image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set image as button's background image (stretchable) for the given state
[self setBackgroundImage:[image stretchableImageWithLeftCapWidth:kCornerRadius topCapHeight:0.0] forState:state];
// Ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = kCornerRadius;
// add colored border
self.layer.borderColor = kStrokeColor.CGColor;
self.layer.borderWidth = kStrokeWidth;
}
@end
usage
- (void)viewDidLoad
{
[myButton setButtonColorNormal:[UIColor redColor]];
}
Assurez-vous que le type de bouton personnalisé ou drawRect peut ne pas être appelé.