uiButton控件上自帶了一個uiLabel類型的子控件和一個uiImageView類型的子控件,如果可以正確使用他們的edgeInsets屬性,就能把button設置成我們想要的樣子。
關於titleEdgeInsets,蘋果文檔的解釋是:The inset or outset margins for the rectangle around the button’s title text,而且imageEdgeInsets也是類似,都沒有講怎么設。事實上,這兩個東西是有聯系的,常常會造成困惑:我只設了其中一個的edgeInsets,為什么button上的圖片和文字布局都變了?
這里是一個同事花一個下午的時間,專門寫一段button的代碼,分析數據,總結出來的小規律,並不權威,但是挺好用的,總結出來分享一下。
默認情況下,imageEdgeInsets和titleEdgeInsets都是0。先不考慮height,
if (button.width小於imageView上image的width){圖像會被壓縮,文字不顯示}
if (button.width < imageView.width + label.width){圖像正常顯示,文字顯示不全}
if (button.width >= imageView.width + label.width){圖像和文字都居中顯示,imageView在左,label在右,中間沒有空隙}
實際app應用中,通常會已知如下參數,布局button
button的width:BUTTON_WIDTH
button上控件imageView的的圖片為image
label上的文字為:@“這是一個測試”
為了不看着頭疼,不寫那么多的常量了,以具體的數字來舉例吧,我們想讓imageView在前,label在后,居中顯示,imageView在button上離左邊界至少為距離10,label離button右邊界為距離為至少為10,imageView和label之間的距離為5,代碼可以如下寫:
NSString *title = @"這是一個測試";
[button setTitle:title forState:UIControlStateNormal];
[button setImage:image forState:UIControlStateNormal];
CGSize strSize = [title sizeWithFont:button.titleLabel.font];
CGFloat totalLen = strSize.width + 5 + image.size.width;
CGFloat edgeLen = (TAGS_BUTTON_WIDTH - totalLen) / 2;
if (edgeLen < 10) {
edgeLen = 10;
}
[button setImageEdgeInsets:UIEdgeInsetsMake(0, edgeLen, 0, edgeLen + 5)];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, edgeLen + 5, 0, edgeLen)];
設置edgeInsets要始終記住的一個原則是:將label和imageView看成一個整體,imageView在前,label在后,中間沒有空隙。。這段代碼中,設置imageEdgeInsets時,imageView與左邊距離為計算好的edgeLen,右邊距是按照button的默認布局,label的右邊與button右邊的距離,就是label實際的右邊應當與button右邊的距離再向左移動5(實際中imageView與label有間距5,默認布局下可沒有這個5,得把這個5讓出來),就是edgeLen + 5。設置titleEdgeInset時,label與右邊為計算好的edgeLen,想象imageView還在label的左邊,與label沒有空隙的話,那這個整體與左邊的距離應該是多少呢?就是edgeLen+5,把間隙的5讓出來嘛。
我們再想一個稍復雜的情況:如果label在左,imageView在右,imageView在button上離右邊界為固定值10,label離button左邊界也為固定值10,應該怎么設呢?可以如下寫代碼:
NSString *title = @"這是一個測試";
[button setTitle:title forState:UIControlStateNormal];
[button setImage:image forState:UIControlStateNormal];
CGSize strSize = [title sizeWithFont:button.titleLabel.font];
[button setImageEdgeInsets:UIEdgeInsetsMake(0, BUTTON_WIDTH - 10 - image.size.width, 0, (10 - strSize.width))];
CGFloat titleRightInset = BUTTON_WIDTH - 10 - strSize.width;
if (titleRightInset < 10 + image.size.width) {
titleRightInset = 10 + image.size.width;
}
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, (10 - image.size.width), 0, titleRightInset)];
解釋這段代碼之前再強調一下UIButton控件的默認布局:imageView在左,label在右,中間沒有空隙。imageView的左側與button的左邊界距離為button的width,去掉右側留出的10,再去掉imageView的width,想像imageView后面還接着有一個label,那么label的右側與button的右邊界距離為10 - strSize.width,所以button的imageEdgeInsets屬性就如上面代碼的設置值了。再看label,它的右側與button右邊界的距離為button的width,去掉左側留出的10,再去掉label的width,為保證label后面能放下一個圖片,圖片后面還有10的空白,故對titleRightInset做了如上的一些調整。想象label的左側還有一個imageView,那么這個整體離button左邊界的距離為10 - image.size.width。
以上只考慮了width方向,height方向與width是獨立的,比width更容易一些。
設button的height:BUTTON_HEIGHT,如果imageView在上,與button上邊界距離為10,label在下,與button下邊界距離為10,可寫如下代碼。
NSString *title = @"這是一個測試";
[button setTitle:title forState:UIControlStateNormal];
[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(10, 0, BUTTON_HEIGHT - 10 - image.size.height , 0)];
[button setTitleEdgeInsets:UIEdgeInsetsMake(BUTTON_HEIGHT - 10 - button.titleLabel.frame.size.height, 0, 10, 0)];
可以看到height方向上,imageView與label獨立變化,不用考慮彼此。