繼承關(guān)系:UIButton : UIControl : UIView : UIResponder : NSObject
一朴上、創(chuàng)建方法
通常,我們創(chuàng)建一個對象會使用[[class alloc] init];方法五嫂,但對于UIButton是不推薦使用此方法的。
原因有二:
UIButton有個按鈕樣式屬性buttonType需要在初始化的時候設(shè)定好矩肩,代碼后期無法改變秸谢。假如使用alloc創(chuàng)建,那么buttonType默認為Custom模式量九。(關(guān)于buttonType詳見后文)
MRC下适掰,如果使用 [[UIButton alloc] init]的方式,需要進行release釋放操作娩鹉;如果使用[UIButton buttonWithType:(UIButtonType)]這種方式攻谁,不需要進行release操作。
所以弯予,代碼創(chuàng)建UIButton方法為:
[UIButton buttonWithType:(UIButtonType)];
二戚宦、按鈕樣式(UIButtonType)
UIButtonType有六種枚舉類型,對應(yīng)外觀如下: 之所以選擇樣式锈嫩,是為了使用該樣式下已經(jīng)默認設(shè)置好的一些屬性受楼。
如Add Contact是一個“+”添加圖形。而Detail Disclosure呼寸、Info Light及Info Dark都是一個“i”信息圖形艳汽,Info Light和Info Dark這倆貨之間我實在找不到有什么異樣,但是這倆貨與DetailDisclosure或者其他樣式的區(qū)別是:這倆貨默認屬性showsTouchWhenHighlighted=YES对雪,這就使得在點擊按鈕的時候(高亮狀態(tài))河狐,這倆貨會散發(fā)出白色的光芒!將背景色調(diào)成黑色看看效果:
最后來說說System和Custom這兩個樣式瑟捣。對于System樣式馋艺,系統(tǒng)為我們預(yù)設(shè)了一些屬性(詳見下文對比部分)。Custom顧名思義是自定義的迈套,可設(shè)置更多屬性捐祠。如果我們在storyboard中設(shè)置Detail Disclosure、Info Light桑李、Info Dark或者Add Contact按鈕的title踱蛀、backgroundImage等屬性,會發(fā)現(xiàn)他們馬上變成Custom樣式贵白;而如果設(shè)置了所有非Custom按鈕的image(前景圖片)屬性率拒,那么這些按鈕也都將變成Custom樣式。說明Custom可操作的屬性還是比較多的禁荒。
System和Custom樣式對比:
1. 對于字體顏色
System默認普通狀態(tài)下為藍色俏橘;Custom默認白色。
2. 對于前景image
Custom樣式下可以顯示前景圖片圈浇,見圖Custom寥掐;System樣式不能顯示前景圖片靴寂,變成了圖System這衰樣…
3. 對于屬性adjustsImageWhenHighlighted @property(nonatomic) BOOL adjustsImageWhenHighlighted;? ? // default is YES. if YES, image is drawn darker when highlighted(pressed) 從官方注釋中可以看到,adjustsImageWhenHighlighted為YES時召耘,使得高亮狀態(tài)(按鈕按下)前景圖片和背景圖片均會變暗百炬。如果將這個屬性值設(shè)為NO,按下按鈕圖片就不會變暗了污它。
經(jīng)我親測剖踊,
System樣式下adjustsImageWhenHighlighted默認為NO,
而Custom樣式下adjustsImageWhenHighlighted默認才為YES衫贬,即此default值說的是Custom樣式德澈。
按道理按下System樣式的按鈕,圖片應(yīng)該不會變暗才對(因為adjustsImageWhenHighlighted默認值為NO)固惯,但是它還是變暗了梆造!這是為什么呢?還請接著看第4點葬毫。
4. 對于高亮狀態(tài)下
如果是System樣式镇辉,高亮狀態(tài)下(即按下按鈕)不止圖片變暗,文字也跟著變暗了贴捡。即使設(shè)置了adjustsImageWhenHighlighted=NO忽肛,或者設(shè)置了高亮狀態(tài)圖片與普通狀態(tài)圖片一致,也是不行烂斋。說明System在高亮狀態(tài)下還會改變另外一個屬性使得按鈕變暗屹逛。但是筆者卻找不出是哪個屬性改變了,估計看官已經(jīng)氣憤難當(dāng)磨刀霍霍了…
如果是Custom汛骂,文字不管在哪種狀態(tài)都不會變暗罕模。而圖片會因為adjustsImageWhenHighlighted默認值為YES變暗,設(shè)置為NO就不變暗了香缺。
三、按鈕屬性
一般來說歇僧,我們設(shè)置對象屬性都會使用點語法图张,但對于UIButton來說,有些屬性是不能使用點語法的诈悍。
設(shè)置屬性注意事項
1. UIButton的非私有屬性(繼承而來的屬性)祸轮,可以使用點語法。
如:
btn.frame = CGRectMake(100, 100, 200, 50);? ? ? // 設(shè)置位置尺寸
? ? btn.backgroundColor = [UIColor purpleColor];? ? // 設(shè)置背景顏色
? ? btn.alpha = 1.0f;? ? ? ? // 設(shè)置透明度
? ? btn.layer.cornerRadius = 5.0;? ? ? ? ? ? ? ? ? // 設(shè)置圓角(5.0是圓角的弧度)
? ? btn.layer.borderWidth = 1.0f;? ? ? ? ? ? ? ? ? // 設(shè)置邊框?qū)挾?/p>
? ? btn.layer.borderColor = [UIColor blackColor].CGColor;? //設(shè)置邊框顏色
? ? btn.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;? ? ? ? // 設(shè)置垂直方向?qū)R方式
? ? btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;? ? // 設(shè)置水平方向?qū)R模式
2. UIButton的私有屬性大多為只讀侥钳,不能使用點語法進行set設(shè)置适袜。
UIButton中所有只讀屬性: @property(nonatomic,readonly) UIButtonType buttonType;
@property(nullable, nonatomic,readonly,strong) NSString *currentTitle;? ? ? ? ? ? // normal/highlighted/selected/disabled. can return nil
@property(nonatomic,readonly,strong) UIColor? *currentTitleColor;? ? ? ? // normal/highlighted/selected/disabled. always returns non-nil. default is white(1,1)
@property(nullable, nonatomic,readonly,strong) UIColor? *currentTitleShadowColor;? // normal/highlighted/selected/disabled.
@property(nullable, nonatomic,readonly,strong) UIImage? *currentImage;? ? ? ? ? ? // normal/highlighted/selected/disabled. can return nil
@property(nullable, nonatomic,readonly,strong) UIImage? *currentBackgroundImage;? // normal/highlighted/selected/disabled. can return nil
@property(nullable, nonatomic,readonly,strong) NSAttributedString *currentAttributedTitle NS_AVAILABLE_IOS(6_0);? // normal/highlighted/selected/disabled. can return nil
@property(nullable, nonatomic,readonly,strong) UILabel? ? *titleLabel NS_AVAILABLE_IOS(3_0);
@property(nullable, nonatomic,readonly,strong) UIImageView *imageView? NS_AVAILABLE_IOS(3_0);
3. UIButton有幾種顯示狀態(tài)(普通、高亮舷夺、選中等)苦酱,每種狀態(tài)對應(yīng)的某些屬性是不同的售貌,如果使用點語法就無法指明是哪種狀態(tài)下的屬性
比如設(shè)置以下屬性的時候需同時表明是在哪個狀態(tài)(State):
- (void)setTitle:(nullable NSString *)title forState:(UIControlState)state;? ? // 設(shè)置標(biāo)題? ? ? ? ? ? ? ?
- (void)setTitleColor:(nullable UIColor *)color forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // 設(shè)置標(biāo)題顏色
- (void)setTitleShadowColor:(nullable UIColor *)color forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // 設(shè)置標(biāo)題陰影顏色
- (void)setImage:(nullable UIImage *)image forState:(UIControlState)state;? // 設(shè)置前景圖片? ? ? ? ? ? ? ? ?
- (void)setBackgroundImage:(nullable UIImage *)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; // 設(shè)置背景圖片
- (void)setAttributedTitle:(nullable NSAttributedString *)title forState:(UIControlState)state NS_AVAILABLE_IOS(6_0);// 設(shè)置帶屬性的標(biāo)題(NSAttributedString類型),設(shè)置麻煩不常用疫萤。
讀取屬性
1. 獲取當(dāng)前狀態(tài)的屬性
使用點語法獲取只讀屬性颂跨,如: btn. currentTitle、btn. currentImage 等等
2. 獲取指定狀態(tài)的屬性
使用對象方法返回屬性:
- (nullable NSString *)titleForState:(UIControlState)state;? ? ? ? ?
- (nullable UIColor *)titleColorForState:(UIControlState)state;
- (nullable UIColor *)titleShadowColorForState:(UIControlState)state;
- (nullable UIImage *)imageForState:(UIControlState)state;
- (nullable UIImage *)backgroundImageForState:(UIControlState)state;
- (nullable NSAttributedString *)attributedTitleForState:(UIControlState)state NS_AVAILABLE_IOS(6_0);
內(nèi)容對齊方式
因為UIButton繼承自UIControl扯饶,而UIControl提供兩個屬性UIControlContentHorizontalAlignment和UIControlContentVerticalAlignment分別用來設(shè)置水平方向和垂直方向的對齊方式恒削,對應(yīng)效果如下:
UIButton中image與backgroundImage區(qū)別
由于System樣式的按鈕不顯示前景圖片(前文有演示),因此以下均是對Custom樣式按鈕進行探討尾序。
1. 層級關(guān)系
創(chuàng)建一個帶有標(biāo)題title钓丰,前景圖片image和背景圖片backgroundImage的按鈕:
小結(jié)一下:
- 視圖Z軸方向由里向外依次為backgroundImage–> image–>title
- image默認居左,title默認居右
2. 內(nèi)容模式
backgroundImage的內(nèi)容模式(contentMode)默認為UIViewContentModeScaleToFill每币,backgroundImage會跟隨按鈕的大小的改變而改變携丁,也就是說背景圖片始終等于按鈕尺寸。
對于image就比較怪:當(dāng)圖片的寬(或高)小于按鈕尺寸時脯爪,image顯示的是原始寬(或高)则北;當(dāng)圖片寬(或高)大于按鈕尺寸時,image被壓縮到與button等寬(或高)的尺寸痕慢。這種內(nèi)容模式我叫不上名兒來尚揣。。掖举。
對于image或者backgroundImage的contentMode屬性快骗,蘋果沒有提供修改的途徑(至少我沒找到)。所以當(dāng)我們使用image的時候塔次,最好先調(diào)好尺寸方篮,對于比較大的圖片,先進行必要的壓縮裁切励负。(不過筆者通常不會這么干藕溅,如果需要自定義比較高的button,我就直接用view來做外觀顯示继榆,然后再套上一個透明的button~)
總結(jié)
1.按鈕的Z軸方向由里向外依次為backgroundImage–> image–>title
2.image默認居左巾表,title默認居右
3.backgroundImage尺寸永遠等于按鈕尺寸
4.對于image:當(dāng)圖片的寬(或高)小于按鈕尺寸時略吨,image顯示的是原始寬(或高);當(dāng)圖片寬(或高)大于按鈕尺寸時鞠苟,image被壓縮到與button等寬(或高)的尺寸。
5.image和backgroundImage的contentMode屬性無法修改。
四.控制狀態(tài)(UIControlState)
在set按鈕的私有屬性的時候当娱,通常會一并forState指明在哪個控制狀態(tài)。那么UIButton總共有幾個狀態(tài)呢趾访?以下是UIControlState枚舉值: typedef NS_OPTIONS(NSUInteger, UIControlState) {
? ? UIControlStateNormal? ? ? = 0,? ? ? ? ? ? // 普通狀態(tài)(按下之前)
? ? UIControlStateHighlighted? = 1 << 0,? ? ? ? // 高亮狀態(tài)(按下ing)
? ? UIControlStateDisabled? ? = 1 << 1,? ? ? ? // 失效狀態(tài)(enable=NO)
? ? UIControlStateSelected? ? = 1 << 2,? ? ? ? // 選中狀態(tài)(selected=YES)
? ? UIControlStateFocused NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 3,? // 聚焦?fàn)顟B(tài)(iOS9.0開始引入,應(yīng)該和3D Touch有關(guān))
? ? UIControlStateApplication? = 0x00FF0000,?
? ? UIControlStateReserved? ? = 0xFF000000? ?
};
我們看到扼鞋,與普通的枚舉不同申鱼,UIControlState是位枚舉。也就是說云头,按鈕可以同時擁有不止一個狀態(tài)溃槐!
if(isSelected == NO),有兩種狀態(tài):UIControlStateNormal 和 UIControlStateHighlighted
if(isSelected == YES)昏滴,也有兩種狀態(tài) UIControlStateSelected 和 UIControlStateSelected | UIControlStateHighlighted
也就是說:當(dāng)沒有選中狀態(tài)下,按下的時候?qū)?yīng)高亮模式(UIControlStateHighlighted)谣殊;而當(dāng)按鈕已經(jīng)是選中狀態(tài),此時再按下按鈕即對應(yīng)高亮模式和選中模式(UIControlStateSelected | UIControlStateHighlighted)宜狐。
五蛇捌、添加事件
前面鋪墊了這么多,接下來該講講UIButton的主要作用了——響應(yīng)事件俭驮。要響應(yīng)事件春贸,首先需給button添加對指定事件的監(jiān)聽機制(add target/action),即添加事件譬圣。
UIButton能響應(yīng)的事件(UIControlEvents)有很多雄坪,枚舉值如下:
UIControlEventTouchDown? ? ? ? ? ? // 單點觸摸按下(用戶點觸屏幕,或者又有新手指落下的時候)
UIControlEventTouchDownRepeat? ? ? // 多點觸摸按下(點觸計數(shù)大于1:用戶按下第二维哈、三、或第四根手指的時候)
? UIControlEventTouchDragInside? ? ? // 當(dāng)一次觸摸在控件內(nèi)拖動
? ? UIControlEventTouchDragOutside? ? ? // 當(dāng)一次觸摸在控件外拖動
? ? UIControlEventTouchDragEnter? ? ? ? // 當(dāng)一次觸摸從控件外拖動到內(nèi)部
? ? UIControlEventTouchDragExit? ? ? ? // 當(dāng)一次觸摸從控件內(nèi)部拖動到外部
? ? UIControlEventTouchUpInside? ? ? ? ? // 所有在控件之內(nèi)觸摸抬起
? ? UIControlEventTouchUpOutside? ? ? ? // 所有在控件之外觸摸抬起(點觸起始必須落在控件內(nèi)部才會發(fā)送通知)
? ? UIControlEventTouchCancel? ? ? ? ? // 所有觸摸取消事件(如一次觸摸因為放上了太多手指而被取消飘庄,或者被上鎖或者電話呼入打斷)
? ? UIControlEventValueChanged? ? ? ? ? // 當(dāng)控件的值發(fā)生改變
UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0)? ? // 當(dāng)控件的首要行為被觸發(fā)跪削,例如button的點擊事件迂求,slider的滑動事件(iOS9.0引入)
UIControlEventEditingDidBegin? ? ? ? ? // 當(dāng)控件中文本開始編輯時
? ? UIControlEventEditingChanged? ? ? ? // 當(dāng)控件中文本發(fā)生改變時
? ? UIControlEventEditingDidEnd? ? ? ? // 當(dāng)控件中文本編輯結(jié)束時
? ? UIControlEventEditingDidEndOnExit? // 當(dāng)文本控件內(nèi)通過按下回車鍵(或等價行為)結(jié)束編輯時
? ? UIControlEventAllTouchEvents? ? ? ? // 所有觸摸事件均觸發(fā)通知
? ? UIControlEventAllEditingEvents? ? ? // 所有文本編輯事件均觸發(fā)通知
? ? UIControlEventApplicationReserved? // 蘋果預(yù)留給應(yīng)用使用,不去理會
? ? UIControlEventSystemReserved? ? ? ? // 蘋果預(yù)留給內(nèi)部框架使用毫玖,不去理會
? ? UIControlEventAllEvents? ? ? ? ? ? ? ? // 所有事件均觸發(fā)通知
添加事件:
? /**
? ? 添加點擊事件
? ? addTarget:(參數(shù)1)? ? 響應(yīng)目標(biāo)(由誰來執(zhí)行響應(yīng)方法)
? ? action:(參數(shù)2)? 調(diào)用方法(即響應(yīng)事件)
? forControlEvents:(參數(shù)3) 事件的類型
? ? */
? ? [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
響應(yīng)方法:
#pragma mark - 按鈕響應(yīng)方法
- (void)btnAction:(UIButton *)btn {
? ? NSLog(@"點擊了按鈕");
}
示例
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
? ? [super viewDidLoad];
? ? // 實例化一個UIButton
? ? UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
? ? /* 設(shè)置屬性 */
? ? btn.frame = CGRectMake(0, 0, 100, 80 );? ? ? // 設(shè)置位置尺寸
? ? btn.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2, [UIScreen mainScreen].bounds.size.height/2);
? ? btn.backgroundColor = [UIColor purpleColor];? ? // 設(shè)置背景顏色
? ? btn.alpha = 1.0f;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 設(shè)置透明度
? ? btn.layer.cornerRadius = 5.0;? ? ? ? ? ? ? ? ? // 設(shè)置圓角(5.0是圓角的弧度)
? ? btn.layer.borderWidth = 1.0f;? ? ? ? ? ? ? ? ? // 設(shè)置邊框?qū)挾?/p>
? ? btn.layer.borderColor = [UIColor blackColor].CGColor;? //設(shè)置邊框顏色
? ? btn.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;? ? ? ? // 設(shè)置垂直方向?qū)R方式
? ? btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;? ? // 設(shè)置水平方向?qū)R模式
// 設(shè)置標(biāo)題文字
? ? [btn setTitle:@"普通" forState:UIControlStateNormal];
? ? [btn setTitle:@"高亮" forState:UIControlStateHighlighted];
? ? [btn setTitle:@"選中" forState:UIControlStateSelected];
? ? [btn setTitle:@"選中狀態(tài)下的高亮" forState:UIControlStateHighlighted|UIControlStateSelected];
? ? // 設(shè)置前景圖
//? ? [btn setImage:[UIImage imageNamed:@"11"] forState:UIControlStateNormal];
? ? // 設(shè)置背景圖
? ? [btn setBackgroundImage:[UIImage imageNamed:@"red"] forState:UIControlStateNormal];
? ? [btn setBackgroundImage:[UIImage imageNamed:@"goodFilling"] forState:UIControlStateHighlighted];
? ? [btn setBackgroundImage:[UIImage imageNamed:@"red"] forState:UIControlStateHighlighted|UIControlStateSelected];
? ? [btn setBackgroundImage:[UIImage imageNamed:@"red"] forState:UIControlStateSelected];
? ? /**
? ? 添加點擊事件
? ? addTarget:(參數(shù)1)? ? 響應(yīng)目標(biāo)(由誰來執(zhí)行響應(yīng)方法)
? ? action:(參數(shù)2)? 調(diào)用方法(即響應(yīng)事件)
? ? forControlEvents:(參數(shù)3) 事件的類型
? ? */
? ? [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
? ? // 添加btn到self.view
? ? [self.view addSubview:btn];
}
#pragma mark - 按鈕響應(yīng)方法
- (void)btnAction:(UIButton *)btn {
? ? NSLog(@"點擊了按鈕");
}
@end