UIButton的默認(rèn)顯示樣式是圖片居左爱咬,文字居右尺借,如下圖1:
但是有時(shí)候我們根據(jù)需求需要調(diào)整按鈕中圖片和標(biāo)題的位置,最常見的就是圖片居上精拟,文字居下顯示的按鈕燎斩,如下圖2所示:
實(shí)現(xiàn)這種居中顯示的圖上文下的按鈕方式有很多,比如最簡(jiǎn)單的方法:自定義View蜂绎,上面放一個(gè)UIButton一個(gè)UILabel子控件栅表。
這里我們介紹其他方法來(lái)實(shí)現(xiàn)UIButton圖片和標(biāo)題的位置調(diào)整:
- 一種是通過(guò)類別(Category)調(diào)整位置;
- 一種是通過(guò)繼承重寫系統(tǒng)方法調(diào)整位置。
通過(guò)類別(Category)調(diào)整位置
通過(guò)類別的方法修改圖片標(biāo)題的位置主要是用了UIButton的兩個(gè)位置屬性:titleEdgeInsets
师枣,imageEdgeInsets
怪瓶。通過(guò)修改按鈕中image
和title
的edgeInsets
來(lái)改變相對(duì)位置。
@property(nonatomic) UIEdgeInsets titleEdgeInsets; // default is UIEdgeInsetsZero
@property(nonatomic) UIEdgeInsets imageEdgeInsets; // default is UIEdgeInsetsZero
UIEdgeInsets有四個(gè)參數(shù):top, left, bottom, right践美,
分別代表上左下右的偏移量洗贰。
top
: 為正數(shù)的時(shí)候,是往下偏移,為負(fù)數(shù)的時(shí)候往上偏移;
left
: 為正數(shù)的時(shí)候往右偏移,為負(fù)數(shù)的時(shí)候往左偏移;
bottom
: 為正數(shù)的時(shí)候往上偏移,為負(fù)數(shù)的時(shí)候往下偏移;
right
:為正數(shù)的時(shí)候往左偏移,為負(fù)數(shù)的時(shí)候往右偏移;
修改按鈕中image和title位置的關(guān)鍵就是正確的設(shè)置這兩個(gè)屬性值的參數(shù),網(wǎng)上很多介紹的方法里寫的都是固定參數(shù)陨倡,如果每次使用都要去計(jì)算的話那就太麻煩了敛滋,這里我們通過(guò)獲取image和title的size來(lái)設(shè)定偏移量,實(shí)現(xiàn)方法的通用玫膀。這也是創(chuàng)建一個(gè)UIButton的category的原因矛缨,方便以后的復(fù)用。
下面貼上category的代碼帖旨,其中計(jì)算titleEdgeInsets
和imageEdgeInsets
的代碼是最核心的地方箕昭,具體的計(jì)算思路可以從代碼里看出來(lái),就不文字介紹了解阅。這里的計(jì)算思路是最關(guān)鍵的地方落竹,只要知道怎么計(jì)算,就可以使用UIButton實(shí)現(xiàn)其他圖文效果货抄,而不止是圖上文下的居中效果述召。
#import <UIKit/UIKit.h>
@interface UIButton (ZXCenterButton)
/**
圖片居上,文字居下蟹地,圖文居中按鈕
@param spaceBetween image和label之間的間距,若設(shè)為nil則距離為0
@param fontSize 標(biāo)題字體大小积暖,若設(shè)為nil則為默認(rèn)字體大小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;
// 計(jì)算標(biāo)題的size
CGSize titleSize = [self string:title sizeWithFont:[UIFont systemFontOfSize:font]];
// 圖片+標(biāo)題的總寬高
CGFloat totalW = imageW + titleSize.width;
CGFloat totalH = imageH + titleSize.height + spaceBetween.floatValue;
// 設(shè)置按鈕圖片偏移
[self setImageEdgeInsets:UIEdgeInsetsMake(-(totalH/2 - imageH/2), totalW/2 - imageW/2, (totalH/2 - imageH/2), -(totalW/2 - imageW/2))];
// 設(shè)置按鈕標(biāo)題偏移
[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;
}
// 根據(jù)文字的長(zhǎng)度、字體 來(lái)計(jì)算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
這種方法使用的時(shí)候注意Button的寬度設(shè)置和title的string長(zhǎng)度怪与,如果按鈕寬度太小夺刑,標(biāo)題的string太長(zhǎng),title無(wú)法全部顯示時(shí)分别,label的寬度計(jì)算會(huì)出現(xiàn)偏差造成布局不居中遍愿。所以使用的時(shí)候要確保title能完全顯示。
通過(guò)繼承調(diào)整位置
通過(guò)繼承的方法調(diào)整image和label的位置其實(shí)也有兩種實(shí)現(xiàn)方法:
- 一種是在
- (void)layoutSubviews
里面重寫self.titleLabel.frame
和self.imageView.frame
的rect值耘斩;
- 另一種就是本文要介紹的沼填,重寫系統(tǒng)方法改變title和image的布局。
通過(guò)繼承需要重寫的兩個(gè)系統(tǒng)方法是:
Objective-C
- (CGRect)titleRectForContentRect:(CGRect)contentRect;
- (CGRect)imageRectForContentRect:(CGRect)contentRect;
具體實(shí)現(xiàn)方法直接見代碼:
- (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;
}
使用這種方法的時(shí)候記得按鈕的標(biāo)題需要設(shè)置為居中括授,此方法來(lái)自我朋友的一篇文章坞笙,詳情請(qǐng)移步,謝謝荚虚。
總結(jié)
解決問(wèn)題的方法有各種各樣薛夜,重要的是能解決問(wèn)題,每個(gè)人的偏好都不一樣曲管。本文介紹的兩種方法却邓,第一種通過(guò)類別修改位置需要對(duì)UIEdgeInsets
屬性理解透徹而且需要有很好的圖形位置想象能力,否則自己很容易搞暈院水,但是類別的好處是以后直接拿來(lái)用就可以腊徙,不用再創(chuàng)建類復(fù)制粘貼了;第二種計(jì)算就相對(duì)來(lái)說(shuō)比較簡(jiǎn)單了檬某,但是需要?jiǎng)?chuàng)建類來(lái)繼承撬腾,復(fù)制粘貼代碼。大家選擇適合自己的就好恢恼。