UIButton自定義圖片文字位置總結

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


圖1.png

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


圖2.png

實現這種居中顯示的圖上文下的按鈕方式有很多,比如最簡單的方法:自定義View,上面放一個UIButton一個UILabel子控件。

這里我們介紹其他方法來實現UIButton圖片和標題的位置調整:

  • 一種是通過類別(Category)調整位置;
  • 一種是通過繼承重寫系統(tǒng)方法調整位置。

通過類別(Category)調整位置

通過類別的方法修改圖片標題的位置主要是用了UIButton的兩個位置屬性:titleEdgeInsetsimageEdgeInsets。通過修改按鈕中imagetitleedgeInsets來改變相對位置。

@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的代碼,其中計算titleEdgeInsetsimageEdgeInsets的代碼是最核心的地方,具體的計算思路可以從代碼里看出來,就不文字介紹了。這里的計算思路是最關鍵的地方,只要知道怎么計算,就可以使用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.frameself.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)建類來繼承,復制粘貼代碼。大家選擇適合自己的就好。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 發(fā)現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 15,635評論 4 61
  • 關于UIButton大家都很熟悉,系統(tǒng)默認的樣式,是image在左,title在右的,如下圖所示: 但是,很多情況...
    流火緋瞳閱讀 25,879評論 16 63
  • 據說這個軟件還蠻好寫的,總要試試看。 然而他們說得markdown又是怎么回事?是在這個頁面里面寫嗎?然而似乎我不...
    三生無忌閱讀 186評論 0 0
  • 希望你帶我吃飯 是因為希望我吃的健康更強壯 希望你給我發(fā)消息是因為想我 想知道我的一切 希望你沒有聯系我的時候忽略...
    小清樓閱讀 152評論 0 0
  • 我的CSDN博客同步發(fā)布:Android OpenGL入門 轉載請注明出處:【huachao1001的簡書:htt...
    huachao1001閱讀 14,256評論 3 67

友情鏈接更多精彩內容