如何改变一个UIButton的背景颜色,而它'突出显示?

在我的应用程序的某些时候,我有一个突出显示的UIButton(例如当用户有他的手指在按钮上),我需要改变背景颜色,而按钮是突出显示的(所以当用户的手指仍然在按钮上)。

我尝试了以下方法:

_button.backgroundColor = [UIColor redColor];

但这并不奏效。颜色保持不变。当按钮没有高亮显示时,我尝试了同一段代码,它工作得很好。我还尝试在改变颜色后调用-setNeedsDisplay,它没有任何效果。

如何强制按钮改变背景颜色?

335640 次浏览

试试tintColor:

_button.tintColor = [UIColor redColor];

如果你有一张图片,试试这个:

-(void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;

或者看看showsTouchWhenHighlighted对你来说是否足够。

不确定这是否解决了你所追求的问题,或者是否符合你的总体开发环境,但我想尝试的第一件事是改变触地事件按钮的背景颜色。

选项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];

你可以重写UIButtonsetHighlighted方法。

objective - 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
}
}

更新:

使用UIButtonBackgroundColor Swift库。

旧:

使用下面的帮助工具创建一个1px x 1px的图像,灰度填充颜色:

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是我的Cocoa Touch静态库的类前缀,称为Acani Utilities,其中AC是Acani, U是Utilities。

在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)
}
}

斯威夫特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)
}
}

你可以子类化UIButton并创建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

笔记(这是一个例子,我知道有问题,这里有一些)

我已经使用了一个NSMutableDictionay来存储每个状态的UIColor,我必须为键做一个讨厌的文本转换,因为UIControlState不是一个很好的直Int。如果它在哪里,你可以init一个数组与许多对象,并使用状态作为一个索引。

因为这一点,你可能会遇到困难,例如一个选定的&禁用按钮,需要更多的逻辑。

另一个问题是,如果你试图同时设置多种颜色,我没有尝试过一个按钮,但如果你能这样做,它可能不会工作

 [btn setBackgroundColor:colour forState:UIControlStateSelected & UIControlStateHighlighted];

我假设这是StoryBoard,没有init和initWithFrame如果你需要,可以添加它们。

你可以使用这个类别添加方法setBackgroundColor: forState:

https://github.com/damienromito/UIButton-setBackgroundColor-forState- < a href = " https://github.com/damienromito/UIButton-setBackgroundColor-forState- " > < / >

覆盖突出显示的变量。 添加@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
}
}
}

不需要将highlighted重写为计算属性。你可以使用属性观察者来触发背景颜色的变化:

override var highlighted: Bool {
didSet {
backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor()
}
}

斯威夫特4

override open var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted ? UIColor.lightGray : UIColor.white
}
}

试试这个!!!!

TouchedDown事件设置一种颜色,TouchUpInside设置另一种颜色。

- (IBAction)touchedDown:(id)sender {
NSLog(@"Touched Down");
btn1.backgroundColor=[UIColor redColor];
}


- (IBAction)touchUpInside:(id)sender {
NSLog(@"TouchUpInside");
btn1.backgroundColor=[UIColor whiteColor];
}

下面是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
}
}
}
}
}

我希望这能有所帮助。

我已经开源了一个UIButton子类,STAButton,以填补这个巨大的功能漏洞。在MIT许可下可用。适用于iOS 7+(我没有测试过旧的iOS版本)。

下面是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)
为了解决这个问题,我创建了一个Category,用UIButtons:
来处理backgroundColor状态 ButtonBackgroundColor-iOS < / p >

可以将类别安装为圆荚体

易于使用objective - c

@property (nonatomic, strong) UIButton *myButton;


...


[self.myButton bbc_backgroundColorNormal:[UIColor redColor]
backgroundColorSelected:[UIColor blueColor]];

斯威夫特更容易使用:

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 !在你的Podfile中使你更容易使用Swift和objective-C。

重要的

我也写了一篇博文提供更多信息

一个更紧凑的解决方案(基于@aleksejs-mjaliks答案):

斯威夫特3/4 +:

override var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted ? .lightGray : .white
}
}

斯威夫特2:

override var highlighted: Bool {
didSet {
backgroundColor = highlighted ? UIColor.lightGrayColor() : UIColor.whiteColor()
}
}

如果你不想重写,这是@timur-bernikowich的答案(斯威夫特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)
}
}

带有斯威夫特3 +语法的UIButton扩展:

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)
< p >原始回答: https://stackoverflow.com/a/30604658/3659227 < / p >

子类化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
}
}
}
}

如果你不重写 只需要设置两个动作 触地得分 touchUpInside < / p >

把它放进去,你就可以去了:
*属性可以在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
}
}

按钮的示例用法可以应用于按钮对象,如下所示:

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)

斯威夫特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)
}
}

没有子类化的斯威夫特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)
class CustomButton: UIButton {


override var isHighlighted: Bool {
didSet {
if (isHighlighted) {
alpha = 0.5
}
else {
alpha = 1
}
}
}


}

使用https://github.com/swordray/UIButtonSetBackgroundColorForState

使用CocoaPods添加到Podfile

pod "UIButtonSetBackgroundColorForState"

斯威夫特

button.setBackgroundColor(.red, forState: .highlighted)

objective - c

[button setBackgroundColor:[UIColor redColor] forState:UIControlStateHighlighted];
extension UIButton {
func setBackgroundColor(color: UIColor, forState: UIControl.State) {
let size = CGSize(width: 1, height: 1)
UIGraphicsBeginImageContext(size)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(color.cgColor)
context?.fill(CGRect(origin: CGPoint.zero, size: size))
let colorImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
setBackgroundImage(colorImage, for: forState)
}


}

斯威夫特5,谢谢@小牛

细节

  • Xcode 11.1 (11A1027), Swift 5

解决方案

import UIKit


extension UIColor {
func createOnePixelImage() -> UIImage? {
let size = CGSize(width: 1, height: 1)
UIGraphicsBeginImageContext(size)
defer { UIGraphicsEndImageContext() }
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.setFillColor(cgColor)
context.fill(CGRect(origin: .zero, size: size))
return UIGraphicsGetImageFromCurrentImageContext()
}
}


extension UIButton {
func setBackground(_ color: UIColor, for state: UIControl.State) {
setBackgroundImage(color.createOnePixelImage(), for: state)
}
}

使用

button.setBackground(.green, for: .normal)

简单的是只使用UIButton扩展

extension UIButton {


func setBackgroundColor(color: UIColor, forState: UIControl.State) {
self.clipsToBounds = true  // add this to maintain corner radius
UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
if let context = UIGraphicsGetCurrentContext() {
context.setFillColor(color.cgColor)
context.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
let colorImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.setBackgroundImage(colorImage, for: forState)
}
}


}

然后用这个

 optionButton.setBackgroundColor(color: UIColor(red:0.09, green:0.42, blue:0.82, alpha:1.0), forState: .selected)


optionButton.setBackgroundColor(color: UIColor(red:0.96, green:0.96, blue:0.96, alpha:1.0), forState: .highlighted)


optionButton.setBackgroundColor(color: UIColor(red:0.96, green:0.96, blue:0.96, alpha:1.0), forState: .normal)

在Swift 5中

对于那些不想使用彩色背景击败所选状态的人

你可以简单地使用#Selector &if语句可以轻松地为每个状态单独更改UIButton的颜色

例如:

    override func viewDidLoad() {
super.viewDidLoad()
self.myButtonOutlet.backgroundColor = UIColor.white  //to reset the button color to its original color ( optionally )
}


@IBOutlet weak var myButtonOutlet: UIButton!{
didSet{  // Button selector and image here
self.myButtonOutlet.setImage(UIImage(systemName: ""), for: UIControl.State.normal)


self.myButtonOutlet.setImage(UIImage(systemName: "checkmark"), for: UIControl.State.selected)






self.myButtonOutlet.addTarget(self, action: #selector(tappedButton), for: UIControl.Event.touchUpInside)
}
}


@objc func tappedButton() {  // Colors selection is here
if self.myButtonOutlet.isSelected == true {


self.myButtonOutlet.isSelected = false
self.myButtonOutlet.backgroundColor = UIColor.white
} else {
self.myButtonOutlet.isSelected = true


self.myButtonOutlet.backgroundColor = UIColor.black
self.myButtonOutlet.tintColor00 = UIColor.white


}
}

你可以简单地使用UIButton上的setBackgroundImage方法,并使用UIImage(color:)初始化器来使用图像,就可以轻松地更改高亮显示/选中的按钮背景颜色,如下所示:

btn.setBackgroundImage(UIImage(color: .black), for: .highlighted)

注意:

如果你对圆角边框使用cornerRadius属性,你必须将clipsToBounds设置为true,这样所选的背景颜色将保留圆角半径值。