在使用UIButton時,很多時候我們需要一個類似於- (void)setBackgroundColor:(UIColor *)color forState:(UIControlState)state這樣的方法,來實現在不同的狀態下使用不同的backgroundColor。遺憾的是,iOS默認並沒有實現這個方法,那我們就自己來實現它。
讓我們先來看看對於設置BackgroundImage,UIButton提供了如下方法:
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default is nil - (UIImage *)backgroundImageForState:(UIControlState)state;
類似的,我們的函數實現聲明如下:
- (void)setBackgroundColor:(UIColor *)color forState:(UIControlState)state; - (UIColor *)backgroundColorForState:(UIControlState)state;
具體實現如下所示,代碼很簡單,不再贅述。
@interface WMButton : UIButton @property (nonatomic, copy) NSString *name; - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state; - (UIColor *)backgroundColorForState:(UIControlState)state; @end
@implementation WMButton
{
NSMutableDictionary *_colors;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
_colors = [NSMutableDictionary dictionary];
}
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
[_colors setValue:backgroundColor forKey:[self keyForState:state]];
}
- (UIColor *)backgroundColorForState:(UIControlState)state
{
return [_colors valueForKey:[self keyForState:state]];
}
- (void)setHighlighted:(BOOL)highlighted
{
// Do original Highlight
[super setHighlighted:highlighted];
// Highlight with new colour OR replace with orignial
NSString *highlightedKey = [self keyForState:UIControlStateHighlighted];
UIColor *highlightedColor = [_colors valueForKey:highlightedKey];
if (highlighted && highlightedColor) {
[super setBackgroundColor:highlightedColor];
} else {
// 由於系統在調用setSelected後,會再觸發一次setHighlighted,故做如下處理,否則,背景色會被最後一次的覆蓋掉。
if ([self isSelected]) {
NSString *selectedKey = [self keyForState:UIControlStateSelected];
UIColor *selectedColor = [_colors valueForKey:selectedKey];
[super setBackgroundColor:selectedColor];
} else {
NSString *normalKey = [self keyForState:UIControlStateNormal];
[super setBackgroundColor:[_colors valueForKey:normalKey]];
}
}
}
- (void)setSelected:(BOOL)selected
{
// Do original Selected
[super setSelected:selected];
// Select with new colour OR replace with orignial
NSString *selectedKey = [self keyForState:UIControlStateSelected];
UIColor *selectedColor = [_colors valueForKey:selectedKey];
if (selected && selectedColor) {
[super setBackgroundColor:selectedColor];
} else {
NSString *normalKey = [self keyForState:UIControlStateNormal];
[super setBackgroundColor:[_colors valueForKey:normalKey]];
}
}
- (NSString *)keyForState:(UIControlState)state
{
return [NSString stringWithFormat:@"state_%d", state];
}
@end使用時,如下調用即可:
[button setBackgroundColor:[UIColor clearColor] forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor clearColor] forState:UIControlStateHighlighted]; [button setBackgroundColor:HotPinkColor forState:UIControlStateSelected];
需要注意的一點是,有些人可能會這樣使用
[button setBackgroundColor:HotPinkColor forState:UIControlStateHighlighted | UIControlStateSelected];
這種用法是不被支持的,雖然可以實現,但是,其實對於iOS默認提供方法- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default is nil這種位於的用法也是不被完全支持的,大家可以試試看。
下面我們再來詳細討論下UIButton切換state的順序問題。
當UIButton被按下時,會啟動一個計時器,每隔一段時間,都會去檢測按鈕是否還處在被按下的狀態。如果系統檢測到它還處於被按下的狀態,則就會切換到UIControlStateHighlighted,否則,恢復到UIControlStateNormal。當你長按後,在當前按鈕的區域抬起手時,會切換到UIControlStateSelected,但是,需要注意的是,這次切換不僅會觸發setSelected:被調用,也會觸發setHighlighted:的一次調用。大家可以看看下面打印出來的Log。
2015-01-08 19:43:58.782 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.227 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.277 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.294 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.327 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.344 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.377 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.494 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.528 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.577 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.660 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.777 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.894 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.927 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:00.944 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.127 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.661 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.696 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.762 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.795 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.862 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.895 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:01.930 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:03.961 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:] 2015-01-08 19:44:05.162 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:]
2015-01-08 19:44:05.328 V |: highlighted = 1 @ WMButton(#38).-[WMButton setHighlighted:]
2015-01-08 19:44:05.346 V |: selected = 1 @ WMButton(#56).-[WMButton setSelected:]
2015-01-08 19:44:05.347 V |: highlighted = 0 @ WMButton(#38).-[WMButton setHighlighted:]