本文主要利用Objective-c 的category 和runtime 特性定制UIButton的布局。UIButton 的图片和标题布局在下面两个方法中返回正确的rect即可。
-(CGRect)titleRectForContentRect:(CGRect)contentRect;
-(CGRect)imageRectForContentRect:(CGRect)contentRect;
可以继承父类重写方法即可。但在这里没有用到继承,而是在Category中使用MethodSwizzle实现。
+load 方法会在实例化对象之前调用,且在main函数之前。常常用来 method swizzle。Category无法添加实例变量,使用了关联对象。
+ (void)load {
Method imageOriginalMethod = class_getInstanceMethod([self class], @selector(imageRectForContentRect:));
Method imageSwizzledMethod = class_getInstanceMethod([self class], @selector(sd_imageRectForContentRect:));
method_exchangeImplementations(imageOriginalMethod, imageSwizzledMethod);
}
- (void)setImageRect:(CGRect)imageRect {
NSValue *value = [NSValue valueWithCGRect:imageRect];
objc_setAssociatedObject(self, @selector(imageRect), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CGRect)imageRect {
NSValue *value = objc_getAssociatedObject(self, @selector(imageRect));
return [value CGRectValue];
}
算了 ,啥也不想说了。看代码。设置title的位置和这玩意儿很像。
- (CGRect)sd_imageRectForContentRect:(CGRect)contentRect {
if (!CGRectIsEmpty(self.imageRect) && !CGRectEqualToRect(self.imageRect, CGRectZero)) {
return self.imageRect;
}
CGRect imgRect = [self sd_imageRectForContentRect:contentRect];
CGRect titRect = [self sd_titleRectForContentRect:contentRect];
if (self.buttonStyle == SDButtonStyleTitleLeft) {
imgRect.origin.x = CGRectGetMaxX(titRect) - CGRectGetWidth(imgRect);
return imgRect;
}
if (self.buttonStyle == SDButtonStyleTitleDown) {
imgRect.origin.x = (CGRectGetWidth(contentRect) - CGRectGetWidth(imgRect))/2.f;
imgRect.origin.y = (CGRectGetHeight(contentRect) - CGRectGetHeight(titRect) - CGRectGetHeight(imgRect) ) /2.f;
return imgRect;
}
if (self.buttonStyle == SDButtonStyleTitleUp) {
imgRect.origin.x = (CGRectGetWidth(contentRect) - CGRectGetWidth(imgRect))/2.f;
imgRect.origin.y = (CGRectGetHeight(contentRect) + CGRectGetHeight(titRect) - CGRectGetHeight(imgRect))/2.f;
return imgRect;
}
return imgRect;
}
使用时,可以直接计算好两者的位置,设置imageRect和titleRect即可。如果你比我还懒,也可以设置buttonStyle。Rect的优先级高于buttonStyle,设置前者之后,后者无效。
有兴趣的在这里拿[demo] [id]。文笔粗烂,懒癌晚期。谢谢。
[id]: https://github.com/doudouapp/ButtonStyle.git