À un moment donné dans mon application, j'ai un UIButton
en surbrillance (par exemple lorsqu'un utilisateur a le doigt sur le bouton) et je dois changer la couleur d'arrière-plan lorsque le bouton est en surbrillance (ainsi lorsque le doigt de l'utilisateur est toujours sur le bouton).
J'ai essayé ce qui suit:
_button.backgroundColor = [UIColor redColor];
Mais ça ne fonctionne pas. La couleur reste la même. J'ai essayé le même morceau de code lorsque le bouton n'est pas en surbrillance et cela fonctionne bien. J'ai aussi essayé d'appeler -setNeedsDisplay
après avoir changé la couleur, cela n'a eu aucun effet.
Comment forcer le bouton pour changer la couleur de fond?
Vous pouvez remplacer la méthode UIButton
setHighlighted
.
Objective-C
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
if (highlighted) {
self.backgroundColor = UIColorFromRGB(0x387038);
} else {
self.backgroundColor = UIColorFromRGB(0x5bb75b);
}
}
Swift 3.0 et Swift 4.1
override open var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted ? UIColor.black : UIColor.white
}
}
Je ne sais pas si cela résout ce que vous recherchez, ou si cela correspond à votre paysage de développement général, mais la première chose que j'essaierais serait de changer la couleur d'arrière-plan du bouton de l'événement TouchDown.
Option 1:
Vous aurez besoin de deux événements à capturer, UIControlEventTouchDown le sera lorsque l'utilisateur appuiera sur le bouton. UIControlEventTouchUpInside et UIControlEventTouchUpOutside seront pour quand ils relâcheront le bouton pour le ramener à l'état normal
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setFrame:CGRectMake(10.0f, 10.0f, 100.0f, 20.f)];
[myButton setBackgroundColor:[UIColor blueColor]];
[myButton setTitle:@"click me:" forState:UIControlStateNormal];
[myButton setTitle:@"changed" forState:UIControlStateHighlighted];
[myButton addTarget:self action:@selector(buttonHighlight:) forControlEvents:UIControlEventTouchDown];
[myButton addTarget:self action:@selector(buttonNormal:) forControlEvents:UIControlEventTouchUpInside];
Option 2:
Renvoie une image créée à partir de la couleur de surbrillance souhaitée. Cela pourrait aussi être une catégorie.
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
puis changez l’état du bouton en surbrillance:
[myButton setBackgroundImage:[self imageWithColor:[UIColor greenColor]] forState:UIControlStateHighlighted];
Il n'est pas nécessaire de remplacer highlighted
en tant que propriété calculée. Vous pouvez utiliser Property Observer pour déclencher le changement de couleur d'arrière-plan:
override var highlighted: Bool {
didSet {
backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor()
}
}
Swift 4
override open var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white
}
}
Dans Swift, vous pouvez remplacer l'accesseur de la propriété en surbrillance (ou sélectionnée) au lieu de remplacer la méthode setHighlighted
override var highlighted: Bool {
get {
return super.highlighted
}
set {
if newValue {
backgroundColor = UIColor.blackColor()
}
else {
backgroundColor = UIColor.whiteColor()
}
super.highlighted = newValue
}
}
Une extension générique pratique dans Swift:
extension UIButton {
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
func setBackgroundColor(color: UIColor, forUIControlState state: UIControlState) {
self.setBackgroundImage(imageWithColor(color), forState: state)
}
}
Swift 3.
extension UIButton {
private func imageWithColor(color: UIColor) -> UIImage? {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
func setBackgroundColor(_ color: UIColor, for state: UIControlState) {
self.setBackgroundImage(imageWithColor(color: color), for: state)
}
}
Ignorer la variable en surbrillance. L'ajout de @IBInspectable
vous permet de modifier la couleur d'arrière-plan surlignée dans le storyboard, ce qui est très pratique également.
class BackgroundHighlightedButton: UIButton {
@IBInspectable var highlightedBackgroundColor :UIColor?
@IBInspectable var nonHighlightedBackgroundColor :UIColor?
override var highlighted :Bool {
get {
return super.highlighted
}
set {
if newValue {
self.backgroundColor = highlightedBackgroundColor
}
else {
self.backgroundColor = nonHighlightedBackgroundColor
}
super.highlighted = newValue
}
}
}
une solution plus compacte (basée sur @ aleksejs-mjaliks answer):
Swift 3/4 +:
override var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted ? .lightGray : .white
}
}
Swift 2:
override var highlighted: Bool {
didSet {
backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor()
}
}
Si vous ne souhaitez pas remplacer, il s'agit d'une version mise à jour de la réponse de @ timur-bernikowich (Swift 4.2):
extension UIButton {
func setBackgroundColor(_ color: UIColor, forState controlState: UIControl.State) {
let colorImage = UIGraphicsImageRenderer(size: CGSize(width: 1, height: 1)).image { _ in
color.setFill()
UIBezierPath(rect: CGRect(x: 0, y: 0, width: 1, height: 1)).fill()
}
setBackgroundImage(colorImage, for: controlState)
}
}
Extension UIButton avec la syntaxe Swift 3 + :
extension UIButton {
func setBackgroundColor(color: UIColor, forState: UIControlState) {
UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
UIGraphicsGetCurrentContext()!.setFillColor(color.cgColor)
UIGraphicsGetCurrentContext()!.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
let colorImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.setBackgroundImage(colorImage, for: forState)
}}
Utilisez-le comme:
YourButton.setBackgroundColor(color: UIColor.white, forState: .highlighted)
Réponse originale: https://stackoverflow.com/a/30604658/3659227
Voici une approche dans Swift, qui utilise une extension UIButton pour ajouter un élément IBInspectable, appelé highlightBackgroundColor. Similaire au sous-classement, sans nécessiter de sous-classe.
private var HighlightedBackgroundColorKey = 0
private var NormalBackgroundColorKey = 0
extension UIButton {
@IBInspectable var highlightedBackgroundColor: UIColor? {
get {
return objc_getAssociatedObject(self, &HighlightedBackgroundColorKey) as? UIColor
}
set(newValue) {
objc_setAssociatedObject(self,
&HighlightedBackgroundColorKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
}
}
private var normalBackgroundColor: UIColor? {
get {
return objc_getAssociatedObject(self, &NormalBackgroundColorKey) as? UIColor
}
set(newValue) {
objc_setAssociatedObject(self,
&NormalBackgroundColorKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
}
}
override public var backgroundColor: UIColor? {
didSet {
if !highlighted {
normalBackgroundColor = backgroundColor
}
}
}
override public var highlighted: Bool {
didSet {
if let highlightedBackgroundColor = self.highlightedBackgroundColor {
if highlighted {
backgroundColor = highlightedBackgroundColor
} else {
backgroundColor = normalBackgroundColor
}
}
}
}
}
J'espère que ça aide.
Vous pouvez utiliser cette catégorie pour ajouter la méthode setBackgroundColor: forState:
https://github.com/damienromito/UIButton-setBackgroundColor-forState-
Ma meilleure solution pour Swift 3 + sans sous-classement.
extension UIButton {
func setBackgroundColor(_ color: UIColor, for state: UIControlState) {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size)
color.setFill()
UIRectFill(rect)
let colorImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
setBackgroundImage(colorImage, for: state)
}
}
Avec cette extension, il est facile de gérer les couleurs pour différents états et elle se décolore automatiquement si la couleur en surbrillance n'est pas fournie.
button.setBackgroundColor(.red, for: .normal)
Sous-classe UIButton et ajoutez des propriétés inspectables pour une utilisation pratique (écrit en Swift 3.0):
final class SelectableBackgroundButton: UIButton {
private struct Constants {
static let animationDuration: NSTimeInterval = 0.1
}
@IBInspectable
var animatedColorChange: Bool = true
@IBInspectable
var selectedBgColor: UIColor = UIColor.blackColor().colorWithAlphaComponent(0.2)
@IBInspectable
var normalBgColor: UIColor = UIColor.clearColor()
override var selected: Bool {
didSet {
if animatedColorChange {
UIView.animateWithDuration(Constants.animationDuration) {
self.backgroundColor = self.selected ? self.selectedBgColor : self.normalBgColor
}
} else {
self.backgroundColor = selected ? selectedBgColor : normalBgColor
}
}
}
override var highlighted: Bool {
didSet {
if animatedColorChange {
UIView.animateWithDuration(Constants.animationDuration) {
self.backgroundColor = self.highlighted ? self.selectedBgColor : self.normalBgColor
}
} else {
self.backgroundColor = highlighted ? selectedBgColor : normalBgColor
}
}
}
}
Essaye ça !!!!
Pour l'événement TouchedDown, définissez une couleur et pour TouchUpInside, définissez l'autre.
- (IBAction)touchedDown:(id)sender {
NSLog(@"Touched Down");
btn1.backgroundColor=[UIColor redColor];
}
- (IBAction)touchUpInside:(id)sender {
NSLog(@"TouchUpInside");
btn1.backgroundColor=[UIColor whiteColor];
}
MISE À JOUR:
Utilisez la bibliothèque IButtonBackgroundColor Swift.
VIEUX:
Utilisez les aides ci-dessous pour créer une image de 1 px x 1 px avec une couleur de remplissage en niveaux de gris:
UIImage *image = ACUTilingImageGray(248/255.0, 1);
ou une couleur de remplissage RVB:
UIImage *image = ACUTilingImageRGB(253/255.0, 123/255.0, 43/255.0, 1);
Ensuite, utilisez cette image
pour définir l’image d’arrière-plan du bouton:
[button setBackgroundImage:image forState:UIControlStateNormal];
#pragma mark - Helpers
UIImage *ACUTilingImageGray(CGFloat gray, CGFloat alpha)
{
return ACUTilingImage(alpha, ^(CGContextRef context) {
CGContextSetGrayFillColor(context, gray, alpha);
});
}
UIImage *ACUTilingImageRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
{
return ACUTilingImage(alpha, ^(CGContextRef context) {
CGContextSetRGBFillColor(context, red, green, blue, alpha);
});
}
UIImage *ACUTilingImage(CGFloat alpha, void (^setFillColor)(CGContextRef context))
{
CGRect rect = CGRectMake(0, 0, 0.5, 0.5);
UIGraphicsBeginImageContextWithOptions(rect.size, alpha == 1, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
setFillColor(context);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Remarque: ACU
est le préfixe de classe de ma bibliothèque statique Cocoa Touch appelée Acani Utilities, où AC correspond à Acani et U à Utilities.
Sur le scénarimage ...
Vous pouvez modifier les paramètres pour chaque état UIButton. Par exemple, sélectionnez "Sélectionné" et vous pourrez ensuite changer la couleur du texte pour cet état.
Pour changer l’arrière-plan lorsque UIButton est en surbrillance:
Vous pouvez sous-classer le UIButton et faire un Nice forState.
colourButton.h
#import <UIKit/UIKit.h>
@interface colourButton : UIButton
-(void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
@end
colourButton.m
#import "colourButton.h"
@implementation colourButton
{
NSMutableDictionary *colours;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
// If colours does not exist
if(!colours)
{
colours = [NSMutableDictionary new]; // The dictionary is used to store the colour, the key is a text version of the ENUM
colours[[NSString stringWithFormat:@"%lu", UIControlStateNormal]] = (UIColor*)self.backgroundColor; // Store the original background colour
}
return self;
}
-(void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state
{
// If it is normal then set the standard background here
if(state & UIControlStateNormal)
{
[super setBackgroundColor:backgroundColor];
}
// Store the background colour for that state
colours[[NSString stringWithFormat:@"%lu", state]]= backgroundColor;
}
-(void)setHighlighted:(BOOL)highlighted
{
// Do original Highlight
[super setHighlighted:highlighted];
// Highlight with new colour OR replace with orignial
if (highlighted && colours[[NSString stringWithFormat:@"%lu", UIControlStateHighlighted]])
{
self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateHighlighted]];
}
else
{
self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateNormal]];
}
}
-(void)setSelected:(BOOL)selected
{
// Do original Selected
[super setSelected:selected];
// Select with new colour OR replace with orignial
if (selected && colours[[NSString stringWithFormat:@"%lu", UIControlStateSelected]])
{
self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateSelected]];
}
else
{
self.backgroundColor = colours[[NSString stringWithFormat:@"%lu", UIControlStateNormal]];
}
}
@end
Notes (Ceci est un exemple, je sais qu'il y a des problèmes et en voici quelques uns)
J'ai utilisé un NSMutableDictionay pour stocker UIColor pour chaque état. Je dois effectuer une conversion de texte désagréable pour la clé, car UIControlState n'est pas un Nice straight Int. Si c'est le cas, vous pouvez initier un tableau contenant autant d'objets et utiliser l'état en tant qu'index.
Pour cette raison, vous avez souvent des difficultés avec, par exemple, un bouton sélectionné et désactivé, un peu plus de logique est nécessaire.
Un autre problème est que si vous essayez de définir plusieurs couleurs en même temps, je n’ai pas essayé avec un bouton, mais si vous pouvez le faire, cela risque de ne pas fonctionner.
[btn setBackgroundColor:colour forState:UIControlStateSelected & UIControlStateHighlighted];
J'ai supposé que c'était StoryBoard, il n'y a pas d'init, initWithFrame, donc ajoutez-les si vous en avez besoin.
J'ai open-source une sous-classe UIButton, STAButton , pour combler ce trou de fonctionnalité. Disponible sous la licence MIT. Fonctionne pour iOS 7+ (je n'ai pas testé avec les anciennes versions iOS).
class CustomButton: UIButton {
override var isHighlighted: Bool {
didSet {
if (isHighlighted) {
alpha = 0.5
}
else {
alpha = 1
}
}
}
}
Pour résoudre ce problème, j'ai créé une catégorie permettant de gérer backgroundColor
États avec UIButtons
:
ButtonBackgroundColor-iOS
Vous pouvez installer la catégorie en tant que pod .
Facile à utiliser avec Objective-C
@property (nonatomic, strong) UIButton *myButton;
...
[self.myButton bbc_backgroundColorNormal:[UIColor redColor]
backgroundColorSelected:[UIColor blueColor]];
Encore plus facile à utiliser avec Swift :
import ButtonBackgroundColor
...
let myButton:UIButton = UIButton(type:.Custom)
myButton.bbc_backgroundColorNormal(UIColor.redColor(), backgroundColorSelected: UIColor.blueColor())
Je vous recommande d'importer le pod avec:
platform :ios, '8.0'
use_frameworks!
pod 'ButtonBackgroundColor', '~> 1.0'
Utilisation de use_frameworks! dans votre podfile, il est plus facile d’utiliser vos pods avec Swift et objective-C.
IMPORTANT
J'ai aussi écrit un article de blog avec plus d'informations.
Essayez ceci si vous avez une image:
-(void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;
ou voyez si showsTouchWhenHighlighted
vous suffit.
Utilisez https://github.com/swordray/UIButtonSetBackgroundColorForState
Ajouter à Podfile en utilisant CocoaPods
pod "UIButtonSetBackgroundColorForState"
Rapide
button.setBackgroundColor(.red, forState: .highlighted)
Objective-C
[button setBackgroundColor:[UIColor redColor] forState:UIControlStateHighlighted];
private var highlightedBackgroundColors = [UIButton:UIColor]()
private var unhighlightedBackgroundColors = [UIButton:UIColor]()
extension UIButton {
@IBInspectable var highlightedBackgroundColor: UIColor? {
get {
return highlightedBackgroundColors[self]
}
set {
highlightedBackgroundColors[self] = newValue
}
}
override open var backgroundColor: UIColor? {
get {
return super.backgroundColor
}
set {
unhighlightedBackgroundColors[self] = newValue
super.backgroundColor = newValue
}
}
override open var isHighlighted: Bool {
get {
return super.isHighlighted
}
set {
if highlightedBackgroundColor != nil {
super.backgroundColor = newValue ? highlightedBackgroundColor : unhighlightedBackgroundColors[self]
}
super.isHighlighted = newValue
}
}
}
Voici le code dans Swift pour sélectionner l'état du bouton:
func imageWithColor(color:UIColor) -> UIImage {
let rect:CGRect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContext(rect.size)
let context:CGContextRef = UIGraphicsGetCurrentContext()!
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let image:UIImage = UIGraphicsGetImageFromCurrentImageContext();
return image;
}
Exemple:
self.button.setImage(self.imageWithColor(UIColor.blackColor()), forState: .Highlighted)
En dessous de UIIImage
l'extension générera un objet image avec le paramètre de couleur spécifié.
extension UIImage {
static func imageWithColor(tintColor: UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
tintColor.setFill()
UIRectFill(rect)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
}
Un exemple d'utilisation d'un bouton peut être appliqué à l'objet bouton comme suit:
setupButton.setBackgroundImage(UIImage.imageWithColor(tintColor: UIColor(displayP3Red: 232/255, green: 130/255, blue: 121/255, alpha: 1.0)), for: UIControlState.highlighted)
setupButton.setBackgroundImage(UIImage.imageWithColor(tintColor: UIColor(displayP3Red: 255/255, green: 194/255, blue: 190/255, alpha: 1.0)), for: UIControlState.normal)
Essayez tintColor
:
_button.tintColor = [UIColor redColor];
Swift 3:
extension UIButton {
private func imageWithColor(color: UIColor) -> UIImage {
let rect = CGRect(x:0.0,y:0.0,width: 1.0,height: 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
func setBackgroundColor(color: UIColor, forUIControlState state: UIControlState) {
self.setBackgroundImage(imageWithColor(color: color), for: state)
}
}
si vous ne remplacez pas, définissez deux actions touchDown touchUpInside