Как изменить цвет фона UIButton, когда он выделен?
В какой-то момент в моем приложении у меня есть выделенный UIButton (например, когда пользователь держит палец на кнопке), и мне нужно изменить цвет фона, пока кнопка выделена (так, пока палец пользователя все еще находится на кнопке).
Я попробовал следующее:
_button.backgroundColor = [UIColor redColor];
Но это не работает. Цвет остается прежним. Я попробовал тот же кусок кода, когда кнопка не подсвечивается, и он работает нормально. Я также попытался вызвать -setNeedsDisplay после изменения цвета, но это не помогло иметь никакого эффекта.
Как заставить кнопку Изменить цвет фона?
27 ответов:
Можно переопределить метод
UIButton'ssetHighlighted.Цель-C
- (void)setHighlighted:(BOOL)highlighted { [super setHighlighted:highlighted]; if (highlighted) { self.backgroundColor = UIColorFromRGB(0x387038); } else { self.backgroundColor = UIColorFromRGB(0x5bb75b); } }Swift 3.0 и Swift 4.1
override open var isHighlighted: Bool { didSet { backgroundColor = isHighlighted ? UIColor.black : UIColor.white } }
Не уверен, решает ли этот вид то, что вы ищете, или соответствует вашему общему ландшафту развития, но первое, что я попробовал бы, было бы изменить цвет фона кнопки на событии приземления.
Вариант 1:
Вам понадобятся два события для захвата, UIControlEventTouchDown будет для того, когда пользователь нажимает кнопку. UIControlEventTouchUpInside и UIControlEventTouchUpOutside будут для того, когда они отпустят кнопку, чтобы вернуть ее в нормальное состояние
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];Вариант 2:
Верните изображение, сделанное из нужного вам цвета подсветки. Это тоже может быть категория.
+ (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; }А затем измените выделенное состояние кнопки:
[myButton setBackgroundImage:[self imageWithColor:[UIColor greenColor]] forState:UIControlStateHighlighted];
Нет необходимости переопределять
highlightedкак вычисляемое свойство. Вы можете использовать свойство observer для запуска изменения цвета фона:override var highlighted: Bool { didSet { backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor() } }Swift 4
override var isHighlighted: Bool { didSet { backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white } }
В swift можно переопределить метод доступа выделенного (или выбранного) свойства вместо переопределения метода setHighlighted
override var highlighted: Bool { get { return super.highlighted } set { if newValue { backgroundColor = UIColor.blackColor() } else { backgroundColor = UIColor.whiteColor() } super.highlighted = newValue } }
Удобное универсальное расширение в 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.0
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) } }
Переопределить выделенную переменную. Добавление
@IBInspectableпозволяет редактировать выделенный backgroundColor в раскадровке, что тоже неплохо.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 } } }
Более компактное решение (на основе ответа @aleksejs-mjaliks):
Свифт 3/4+:
override var isHighlighted: Bool { didSet { backgroundColor = isHighlighted ? .lightGray : .white } }Swift 2:
override var highlighted: Bool { didSet { backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor() } }
Расширение UIButton с 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) }}Используйте его как:
YourButton.setBackgroundColor(color: UIColor.white, forState: .highlighted)Оригинальный Ответ: https://stackoverflow.com/a/30604658/3659227
Вы можете использовать эту категорию, которая добавляет метод setBackgroundColor: forState:
Https://github.com/damienromito/UIButton-setBackgroundColor-forState-
Вот подход в Swift, использующий расширение UIButton для добавления IBInspectable, называемого highlightedBackgroundColor. Аналогично подклассу, не требуя подкласса.
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 } } } } }Надеюсь, это поможет.
Мое лучшее решение для Swift 3+ без подклассов.
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) } }С помощью этого расширения легко управлять цветами для различных состояний, и он будет автоматически исчезать ваш нормальный цвет, если выделенный цвет не предусмотрен.
button.setBackgroundColor(.red, for: .normal)
Обновление:
Используйте библиотеку Swift UIButtonBackgroundColor.
Старый:
Используйте помощники ниже, чтобы создать изображение размером 1 x 1 px с оттенками серого цвета заливки:
UIImage *image = ACUTilingImageGray(248/255.0, 1);Или цвет заливки RGB:
UIImage *image = ACUTilingImageRGB(253/255.0, 123/255.0, 43/255.0, 1);Затем используйте это
image, чтобы установить фоновое изображение кнопки:[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; }Примечание:
ACU- это префикс класс мое прикосновение статическую библиотеку какао называется Acani коммунальные услуги, где переменный ток для Acani и U за коммунальные услуги.
Попробуйте это !!!!
Для события TouchedDown установите один цвет, а для TouchUpInside-другой.
- (IBAction)touchedDown:(id)sender { NSLog(@"Touched Down"); btn1.backgroundColor=[UIColor redColor]; } - (IBAction)touchUpInside:(id)sender { NSLog(@"TouchUpInside"); btn1.backgroundColor=[UIColor whiteColor]; }
Подкласс UIButton и добавить проверяемые свойства для удобного использования (написано в 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 } } } }
Попробуйте сделать это, если у вас есть изображение:
-(void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;Или посмотрите, достаточно ли вам
showsTouchWhenHighlighted.
Вы можете подкласс UIButton и сделать хороший forState.
Цветная кнопка.h
#import <UIKit/UIKit.h> @interface colourButton : UIButton -(void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state; @endЦветная кнопка.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Примечания (это пример, я знаю, что есть проблемы, и вот некоторые)
Я использовал NSMutableDictionay для хранения UIColor для каждого состояния, я должен сделать неприятное преобразование текста для ключа, поскольку UIControlState не является хорошим прямым Int. Если это где вы могли бы init массив с таким количеством объектов и использовать Состояние как индекс.
Из-за этого у многих возникают трудности, например, с выбранной и отключенной кнопкой, требуется еще немного логики.
Другая проблема заключается в том, что если вы попытаетесь установить несколько цветов одновременно, я не пробовал с помощью кнопки, но если вы можете это сделать, это может не сработать
Я предположил, что это раскадровка, нет init, initWithFrame, поэтому добавьте их, если они вам нужны.[btn setBackgroundColor:colour forState:UIControlStateSelected & UIControlStateHighlighted];
У меня есть открытый подкласс UIButton, STAButton, чтобы заполнить эту зияющую функциональную дыру. Доступно по лицензии MIT. Работает для iOS 7+ (я не тестировал с более старыми версиями iOS).
Чтобы решить эту проблему, я создал категорию для обработки состояний
backgroundColorс помощьюUIButtons:
ButtonBackgroundColor-iOSВы можете установить категорию какpod .
Простота использования с Objective-C
@property (nonatomic, strong) UIButton *myButton; ... [self.myButton bbc_backgroundColorNormal:[UIColor redColor] backgroundColorSelected:[UIColor blueColor]];Еще проще использовать с Swift :
import ButtonBackgroundColor ... let myButton:UIButton = UIButton(type:.Custom) myButton.bbc_backgroundColorNormal(UIColor.redColor(), backgroundColorSelected: UIColor.blueColor())Я рекомендую вам импортировать модуль с:
platform :ios, '8.0' use_frameworks! pod 'ButtonBackgroundColor', '~> 1.0'Используя use_frameworks! в файл контейнера облегчает использование ваши стручки с быстрой и цель-С.
Важно
Я также написал сообщение в блоге с дополнительной информацией.
Вот код в Swift для выбора состояния кнопки:
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; }Пример:
self.button.setImage(self.imageWithColor(UIColor.blackColor()), forState: .Highlighted)
Бросьте его, и вы можете идти:
* proerty можно установить в IB, и если не установлен выделенный фон, фон не изменится при нажатии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 } } }
Ниже
UIIImageрасширение будет генерировать объект изображения с заданным цветовым параметром.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 } }Пример использования кнопки может быть применен к объекту button следующим образом:
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)
class CustomButton: UIButton { override var isHighlighted: Bool { didSet { if (isHighlighted) { alpha = 0.5 } else { alpha = 1 } } } }
Использовать https://github.com/swordray/UIButtonSetBackgroundColorForState
Добавить в Подфайл с помощью CocoaPods
pod "UIButtonSetBackgroundColorForState"Swift
button.setBackgroundColor(.red, forState: .highlighted)Цель-C
[button setBackgroundColor:[UIColor redColor] forState:UIControlStateHighlighted];
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) } }
Это возможно, установив его через XIB. В xib установить выделенный оттенок цвета, как u желание при нажатии на кнопку. Поскольку программно правильного подхода к этому до сих пор нет. Так что это легко для вас, установив его в XIB .
Это будет прекрасно работать:) наслаждайтесь..
Comments