今天在項目中突然發(fā)現(xiàn)一個奇怪的問題,按鈕在isSelected == YES的時候再次點擊,按鈕的圖片變成了normal狀態(tài)的圖片(其實這個問題不奇怪,只是之前一直沒有注意這個細(xì)節(jié)).
1 源代碼如下:
創(chuàng)建代碼
UIButton *arrowBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 900, 27)];
[arrowBtn setImage:[UIImage imageNamed:@"jiantou1"] forState:UIControlStateNormal];
[arrowBtn setImage:[UIImage imageNamed:@"jiantou2"] forState:UIControlStateSelected];
[superView addSubview:arrowBtn];
注:防止出現(xiàn)版權(quán)問題,其中變量的名字和圖片的名字,我做了調(diào)整,但是方法是原來的方法;
點擊效果如下:
2 解決方案(文章后邊有更好的解決辦法)
我自己想的最直接的辦法解決這個問題是不用按鈕自帶的狀態(tài),直接在點擊事件里動態(tài)改變按鈕正常狀態(tài)的圖片
具體代碼:
創(chuàng)建代碼
UIButton *arrowBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 900, 27)];
[arrowBtn setImage:[UIImage imageNamed:@"jiantou1"] forState:UIControlStateNormal];
[superView addSubview:arrowBtn];
[arrowBtn addTarget:self action:@selector(arrowBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
點擊事件
-(void)arrowBtnClicked:(UIButton*)btn{
if(self.isSelected){
self.isSelected = NO;
[btn setImage:[UIImage imageNamed:@"上"] forState:UIControlStateNormal];
}else{
self.isSelected = YES;
[btn setImage:[UIImage imageNamed:@"下"] forState:UIControlStateNormal];
}
}
二 探索發(fā)現(xiàn)
按鈕在isSelected == YES的時候再次點擊,按鈕的圖片變成了normal狀態(tài)的圖片
通過這個現(xiàn)象我提出疑問,為什么會是這種效果,難道在isSelected == YES的時候再次點擊是normal狀態(tài)嗎?
為了解決這個問題,我首先想到的是看一下UIButton的狀態(tài)的API
typedef NS_OPTIONS(NSUInteger, UIControlState) {
UIControlStateNormal = 0,
UIControlStateHighlighted = 1 << 0, // used when UIControl isHighlighted is set
UIControlStateDisabled = 1 << 1,
UIControlStateSelected = 1 << 2, // flag usable by app (see below)
UIControlStateFocused NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 3, // Applicable only when the screen supports focus
UIControlStateApplication = 0x00FF0000, // additional flags available for application use
UIControlStateReserved = 0xFF000000 // flags reserved for internal framework use
};
我發(fā)現(xiàn)按鈕的狀態(tài)是位枚舉,不是普通的枚舉,也就是說按鈕可以有不止一個狀態(tài),那我猜想按鈕在isSelected == YES時,再點擊的時候狀態(tài)應(yīng)該不是normal狀態(tài)而是其他狀態(tài).
后來我搜索了一下相關(guān)的說明.在這里
http://commandshift.co.uk/blog/2013/04/16/uibutton-control-states/
發(fā)現(xiàn)了相關(guān)的說明:
So why would you care about this? Say you were implementing an edit button or
a selection button with text, a background image and an image. You want different
text and images for the selected and unselected states (e.g. Editand Done),
but you also want to modify the images or background images when highlighting -
if you’re creating your own theme for the app then the default darkening or
dimming might not be what you want.
So you actually need four images - normal, highlighted, selected
and selected + highlighted.
This is achieved like so:
[self.button setImage:normal forState:UIControlStateNormal];
[self.button setImage:highlighted forState:UIControlStateHighlighted];
[self.button setImage:selected forState:UIControlStateSelected];
[self.button setImage:selectedHighlighted forState:UIControlStateSelected | UIControlStateHighlighted];
也就是說按鈕其實有兩類,四種狀態(tài)
1 在isSelected == NO的時候,有兩種分別對應(yīng) UIControlStateNormal 和 UIControlStateHighlighted
2 在isSelected == YES的時候,有兩種分別對應(yīng) UIControlStateSelected 和 UIControlStateSelected | UIControlStateHighlighted
由以上的說明,我猜想出現(xiàn) “按鈕在isSelected == YES的時候再次點擊,按鈕的圖片變成了normal狀態(tài)的圖片”情況的原因就是沒有設(shè)置UIControlStateSelected | UIControlStateHighlighted狀態(tài)的圖片,系統(tǒng)默認(rèn)會顯示UIControlStateNormal狀態(tài)的圖片
所以又產(chǎn)生了第二種解決辦法,將按鈕的
UIControlStateSelected | UIControlStateHighlighted狀態(tài)的圖片
設(shè)置成UIControlStateSelected狀態(tài)的圖片
代碼如下:
UIButton *arrowBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 900, 27)];
[arrowBtn setImage:[UIImage imageNamed:@"jiantou1"] forState:UIControlStateNormal];
[arrowBtn setImage:[UIImage imageNamed:@"jiantou2"] forState:UIControlStateSelected];
[arrowBtn setImage:[UIImage imageNamed:@"jiantou2"] forState:UIControlStateSelected | UIControlStateHighlighted];
[superView addSubview:arrowBtn];
三 延展
通過按鈕的圖片也就是image,我猜想類似的應(yīng)該也適用于
– (void)setTitle:(nullable NSString *)title forState:(UIControlState)state; // default is nil. title is assumed to be single line
– (void)setTitleColor:(nullable UIColor *)color forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default if nil. use opaque white
– (void)setTitleShadowColor:(nullable UIColor *)color forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default is nil. use 50% black
– (void)setImage:(nullable UIImage *)image forState:(UIControlState)state; // default is nil. should be same size if different for different states
– (void)setBackgroundImage:(nullable UIImage *)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // default is nil
– (void)setAttributedTitle:(nullable NSAttributedString *)title forState:(UIControlState)state NS_AVAILABLE_IOS(6_0); // default is nil. title is assumed to be single line
本文就不做相關(guān)測試了,有興趣的同學(xué)可以試試!