UIButton(干貨)--教你如何利用runtime自定義UIButton的titleLabel以及image的frame

最近做項目,會用到許多的類似美團(tuán)首頁button的效果,之前做法都是自定義view,view上添加button以及l(fā)abel來做出相同的效果,但是今天我教你極為簡便的方法,只需要自定義button就能實現(xiàn)同一個bt上titleLabel與image互換!

想要的效果:


例子

實際效果:哈哈,需要各位大佬們自己去美化


自定義bt層級關(guān)系
正面效果

傳送門:https://github.com/JonesCxy/UIButton
不廢話,直接上代碼:
category.h

#import <UIKit/UIKit.h>

@interface UIButton (Layout)

@property (nonatomic,assign) CGRect titleRect;
@property (nonatomic,assign) CGRect imageRect;

@end

category.m

#import "UIButton+Layout.h"
#import <objc/runtime.h>

@interface UIButton ()

@end

@implementation UIButton (Layout)

#pragma mark - ************* 通過運行時動態(tài)添加關(guān)聯(lián) ******************
//定義關(guān)聯(lián)的Key
static const char * titleRectKey = "yl_titleRectKey";
- (CGRect)titleRect {
    
    return [objc_getAssociatedObject(self, titleRectKey) CGRectValue];
}

- (void)setTitleRect:(CGRect)rect {
    
    objc_setAssociatedObject(self, titleRectKey, [NSValue valueWithCGRect:rect], OBJC_ASSOCIATION_RETAIN);
}

//定義關(guān)聯(lián)的Key
static const char * imageRectKey = "yl_imageRectKey";
- (CGRect)imageRect {
    
    NSValue * rectValue = objc_getAssociatedObject(self, imageRectKey);
    
    return [rectValue CGRectValue];
}

- (void)setImageRect:(CGRect)rect {
    
    objc_setAssociatedObject(self, imageRectKey, [NSValue valueWithCGRect:rect], OBJC_ASSOCIATION_RETAIN);
}

#pragma mark - ************* 通過運行時動態(tài)替換方法 ******************
+ (void)load {
    
    MethodSwizzle(self,@selector(titleRectForContentRect:),@selector(override_titleRectForContentRect:));
    MethodSwizzle(self,@selector(imageRectForContentRect:),@selector(override_imageRectForContentRect:));
}

void MethodSwizzle(Class c,SEL origSEL,SEL overrideSEL)
{
    
    Method origMethod = class_getInstanceMethod(c, origSEL);
    Method overrideMethod= class_getInstanceMethod(c, overrideSEL);
    
    //運行時函數(shù)class_addMethod 如果發(fā)現(xiàn)方法已經(jīng)存在怔揩,會失敗返回捉邢,也可以用來做檢查用:
    if(class_addMethod(c, origSEL, method_getImplementation(overrideMethod),method_getTypeEncoding(overrideMethod)))
    {
        //如果添加成功(在父類中重寫的方法),再把目標(biāo)類中的方法替換為舊有的實現(xiàn):
        class_replaceMethod(c,overrideSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    }
    else
    {
        //addMethod會讓目標(biāo)類的方法指向新的實現(xiàn)商膊,使用replaceMethod再將新的方法指向原先的實現(xiàn)伏伐,這樣就完成了交換操作。
        method_exchangeImplementations(origMethod,overrideMethod);
    }
}
      
- (CGRect)override_titleRectForContentRect:(CGRect)contentRect {

    if (!CGRectIsEmpty(self.titleRect) && !CGRectEqualToRect(self.titleRect, CGRectZero)) {
        return self.titleRect;
    }
    return [self override_titleRectForContentRect:contentRect];

}

- (CGRect)override_imageRectForContentRect:(CGRect)contentRect {
    
    if (!CGRectIsEmpty(self.imageRect) && !CGRectEqualToRect(self.imageRect, CGRectZero)) {
        return self.imageRect;
    }
    return [self override_imageRectForContentRect:contentRect];
}

- (void)setTitleRect:(CGRect )titleRect ImageRect:(CGRect )imageRect {
    
    self.titleRect = titleRect;
    self.imageRect = imageRect;
}

@end

自定義Bt.h

#import <UIKit/UIKit.h>

@interface CxyButton : UIButton


@property(assign,nonatomic)CGRect titleRect;

@property(assign,nonatomic)CGRect imageRect;

@end

自定義Bt.m

#import "CxyButton.h"

@implementation CxyButton

- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
    }
    return self;
}


-(CGRect)titleRectForContentRect:(CGRect)contentRect{

    if (!CGRectIsEmpty(self.titleRect) && !CGRectEqualToRect(self.titleRect, CGRectZero)) {
        
        return self.titleRect;
    }
    
    
    return [super titleRectForContentRect:contentRect];

}


-(CGRect)imageRectForContentRect:(CGRect)contentRect{

    if (!CGRectIsEmpty(self.imageRect)&&!CGRectEqualToRect(self.imageRect, CGRectZero)) {
        return self.imageRect;
    }
    return [super imageRectForContentRect:contentRect];
}


@end

ViewControll.m

- (void)viewDidLoad {
    [super viewDidLoad];
    CxyButton *bt = [CxyButton buttonWithType:(UIButtonTypeCustom)];
    bt.imageRect = CGRectMake(0, 0, 20, 20);
    bt.titleRect = CGRectMake(20, 0, 80, 20);
    bt.frame = CGRectMake(100, 100, 100, 20);
    [bt setImage:[UIImage imageNamed:@"heart-1"] forState:(UIControlStateNormal)];
    [bt setTitle:@"我就是我" forState:(UIControlStateNormal)];
    bt.backgroundColor = [UIColor redColor];
    [self.view addSubview:bt];
    
    CxyButton *bt2 = [CxyButton buttonWithType:(UIButtonTypeCustom)];
    bt2.imageRect = CGRectMake(0, 0, 30, 30);
    bt2.titleRect = CGRectMake(0, 20, 30, 80);
    bt2.frame = CGRectMake(100, 150, 30, 100);
    [bt2 setImage:[UIImage imageNamed:@"heart-2"] forState:(UIControlStateNormal)];
    [bt2 setTitle:@"我" forState:(UIControlStateNormal)];
    bt2.backgroundColor = [UIColor greenColor];
    [self.view addSubview:bt2];
    
}

簡介:利用運行時將bt的titleLabel與image位置動態(tài)改變,在給bt賦值時,只需要重寫title與image的rect即可.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晕拆,一起剝皮案震驚了整個濱河市藐翎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌实幕,老刑警劉巖吝镣,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昆庇,居然都是意外死亡末贾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門整吆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拱撵,“玉大人辉川,你說我怎么就攤上這事∷┎猓” “怎么了员串?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長昼扛。 經(jīng)常有香客問我寸齐,道長,這世上最難降的妖魔是什么抄谐? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任渺鹦,我火速辦了婚禮,結(jié)果婚禮上蛹含,老公的妹妹穿的比我還像新娘毅厚。我一直安慰自己,他們只是感情好浦箱,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布吸耿。 她就那樣靜靜地躺著,像睡著了一般酷窥。 火紅的嫁衣襯著肌膚如雪咽安。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天蓬推,我揣著相機與錄音妆棒,去河邊找鬼。 笑死沸伏,一個胖子當(dāng)著我的面吹牛糕珊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毅糟,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼红选,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了姆另?” 一聲冷哼從身側(cè)響起喇肋,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜕青,沒想到半個月后苟蹈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡右核,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了渺绒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贺喝。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡菱鸥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躏鱼,到底是詐尸還是另有隱情氮采,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布染苛,位于F島的核電站鹊漠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茶行。R本人自食惡果不足惜躯概,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望畔师。 院中可真熱鬧娶靡,春花似錦、人聲如沸看锉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伯铣。三九已至呻此,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腔寡,已是汗流浹背趾诗。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蹬蚁,地道東北人恃泪。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像犀斋,于是被迫代替她去往敵國和親贝乎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,730評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫叽粹、插件览效、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,058評論 4 62
  • 尊敬的各位家長,大家好:周末作業(yè)安排如下虫几。 1.學(xué)會炒一個菜锤灿。 2.硬筆基本筆畫練習(xí):長橫。要求是寫端正辆脸,寫好但校,不...
    許圣高閱讀 293評論 0 0
  • 命令提示下:cpu信息 wmic cpu get name^,extclock^,cpustatus^,descr...
    cndeng閱讀 3,173評論 0 0
  • 1 樊勝美是這個電視我最不喜歡的角色之一,她的自尊心太強啡氢,而且他可憐的自尊心讓她不敢以真實的心態(tài)去面對朋友状囱,面對愛...
    逆光blacklight閱讀 291評論 0 1