UIButton的默認顯示樣式是圖片居左,文字居右,如下圖1:

但是有時候我們根據需求需要調整按鈕中圖片和標題的位置,最常見的就是圖片居上,文字居下顯示的按鈕,如下圖2所示:

實現這種居中顯示的圖上文下的按鈕方式有很多,比如最簡單的方法:自定義View,上面放一個UIButton一個UILabel子控件。
這里我們介紹其他方法來實現UIButton圖片和標題的位置調整:
- 一種是通過類別(Category)調整位置;
- 一種是通過繼承重寫系統(tǒng)方法調整位置。
通過類別(Category)調整位置
通過類別的方法修改圖片標題的位置主要是用了UIButton的兩個位置屬性:titleEdgeInsets,imageEdgeInsets。通過修改按鈕中image和title的edgeInsets來改變相對位置。
@property(nonatomic) UIEdgeInsets titleEdgeInsets; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets imageEdgeInsets; // default is UIEdgeInsetsZero
UIEdgeInsets有四個參數:top, left, bottom, right,分別代表上左下右的偏移量。
top: 為正數的時候,是往下偏移,為負數的時候往上偏移;
left: 為正數的時候往右偏移,為負數的時候往左偏移;
bottom: 為正數的時候往上偏移,為負數的時候往下偏移;
right:為正數的時候往左偏移,為負數的時候往右偏移;
修改按鈕中image和title位置的關鍵就是正確的設置這兩個屬性值的參數,網上很多介紹的方法里寫的都是固定參數,如果每次使用都要去計算的話那就太麻煩了,這里我們通過獲取image和title的size來設定偏移量,實現方法的通用。這也是創(chuàng)建一個UIButton的category的原因,方便以后的復用。
下面貼上category的代碼,其中計算titleEdgeInsets和imageEdgeInsets的代碼是最核心的地方,具體的計算思路可以從代碼里看出來,就不文字介紹了。這里的計算思路是最關鍵的地方,只要知道怎么計算,就可以使用UIButton實現其他圖文效果,而不止是圖上文下的居中效果。
#import <UIKit/UIKit.h>
@interface UIButton (ZXCenterButton)
/**
圖片居上,文字居下,圖文居中按鈕
@param spaceBetween image和label之間的間距,若設為nil則距離為0
@param fontSize 標題字體大小,若設為nil則為默認字體大小17
*/
-(instancetype)initCenterBtnWithFrame:(CGRect)frame
spaceBetween:(NSNumber*)spaceBetween
imageNamed:(NSString *)imageName
title:(NSString *)title
fontSize:(NSNumber*)fontSize;
@end
#import "UIButton+ZXCenterButton.h"
@implementation UIButton (ZXCenterButton)
-(instancetype)initCenterBtnWithFrame:(CGRect)frame spaceBetween:(NSNumber*)spaceBetween imageNamed:(NSString *)imageName title:(NSString *)title fontSize:(NSNumber*)fontSize{
if (self = [super initWithFrame:frame]) {
CGFloat font = fontSize == nil ? 17 : [fontSize floatValue];
[self setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
[self setTitle:title forState:UIControlStateNormal];
self.titleLabel.font = [UIFont systemFontOfSize:font];
// 圖片的寬高
CGFloat imageW = self.imageView.frame.size.width;
CGFloat imageH = self.imageView.frame.size.height;
// 計算標題的size
CGSize titleSize = [self string:title sizeWithFont:[UIFont systemFontOfSize:font]];
// 圖片+標題的總寬高
CGFloat totalW = imageW + titleSize.width;
CGFloat totalH = imageH + titleSize.height + spaceBetween.floatValue;
// 設置按鈕圖片偏移
[self setImageEdgeInsets:UIEdgeInsetsMake(-(totalH/2 - imageH/2), totalW/2 - imageW/2, (totalH/2 - imageH/2), -(totalW/2 - imageW/2))];
// 設置按鈕標題偏移
[self setTitleEdgeInsets:UIEdgeInsetsMake((totalH/2 - titleSize.height/2), -(totalW/2 - titleSize.width/2), -(totalH/2 - titleSize.height/2), totalW/2 - titleSize.width/2)];
}
return self;
}
// 根據文字的長度、字體 來計算size
- (CGSize)string:(NSString *)string sizeWithFont:(UIFont *)font{
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
attrs[NSFontAttributeName] = font;
CGSize maxSize = CGSizeMake(MAXFLOAT, MAXFLOAT);
return [string boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;
}
@end
這種方法使用的時候注意Button的寬度設置和title的string長度,如果按鈕寬度太小,標題的string太長,title無法全部顯示時,label的寬度計算會出現偏差造成布局不居中。所以使用的時候要確保title能完全顯示。
通過繼承調整位置
通過繼承的方法調整image和label的位置其實也有兩種實現方法:
- 一種是在
- (void)layoutSubviews里面重寫self.titleLabel.frame和self.imageView.frame的rect值;
- 另一種就是本文要介紹的,重寫系統(tǒng)方法改變title和image的布局。
通過繼承需要重寫的兩個系統(tǒng)方法是:
Objective-C
- (CGRect)titleRectForContentRect:(CGRect)contentRect;
- (CGRect)imageRectForContentRect:(CGRect)contentRect;
具體實現方法直接見代碼:
- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
CGRect titleRect = CGRectMake(0, CGRectGetHeight(self.bounds)/3 * 2, CGRectGetWidth(self.bounds),CGRectGetHeight(self.bounds)/3);
return titleRect;
}
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
CGFloat width = CGRectGetWidth(self.bounds);
// 圖片占按鈕高度的2/3
CGRect imageRect = CGRectMake(0, 0, width, CGRectGetHeight(self.bounds)/3 * 2);
return imageRect;
}
使用這種方法的時候記得按鈕的標題需要設置為居中,此方法來自我朋友的一篇文章,詳情請移步,謝謝。
總結
解決問題的方法有各種各樣,重要的是能解決問題,每個人的偏好都不一樣。本文介紹的兩種方法,第一種通過類別修改位置需要對UIEdgeInsets屬性理解透徹而且需要有很好的圖形位置想象能力,否則自己很容易搞暈,但是類別的好處是以后直接拿來用就可以,不用再創(chuàng)建類復制粘貼了;第二種計算就相對來說比較簡單了,但是需要創(chuàng)建類來繼承,復制粘貼代碼。大家選擇適合自己的就好。