最近做項目,會用到許多的類似美團(tuán)首頁button的效果,之前做法都是自定義view,view上添加button以及l(fā)abel來做出相同的效果,但是今天我教你極為簡便的方法,只需要自定義button就能實現(xiàn)同一個bt上titleLabel與image互換!
想要的效果:
實際效果:哈哈,需要各位大佬們自己去美化
傳送門: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即可.