ios-unity/Classes_cocos/LBXNative/UIImageView+CornerRadius.m
2022-11-25 15:08:47 +08:00

249 lines
8.1 KiB
Objective-C

//
// UIImageView+CornerRadius.m
// MyPractise
//
#import "UIImageView+CornerRadius.h"
#import <objc/runtime.h>
const char kRadius;
const char kRoundingCorners;
const char kIsRounding;
const char kHadAddObserver;
const char kProcessedImage;
const char kBorderWidth;
const char kBorderColor;
@interface UIImageView ()
@property (assign, nonatomic) CGFloat radius;
@property (assign, nonatomic) UIRectCorner roundingCorners;
@property (assign, nonatomic) CGFloat borderWidth;
@property (strong, nonatomic) UIColor *borderColor;
@property (assign, nonatomic) BOOL hadAddObserver;
@property (assign, nonatomic) BOOL isRounding;
@end
@implementation UIImageView (CornerRadius)
/**
* @brief init the Rounding UIImageView, no off-screen-rendered
*/
- (instancetype)initWithRoundingRectImageView {
self = [super init];
if (self) {
[self zy_cornerRadiusRoundingRect];
}
return self;
}
/**
* @brief init the UIImageView with cornerRadius, no off-screen-rendered
*/
- (instancetype)initWithCornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
self = [super init];
if (self) {
[self zy_cornerRadiusAdvance:cornerRadius rectCornerType:rectCornerType];
}
return self;
}
/**
* @brief attach border for UIImageView with width & color
*/
- (void)zy_attachBorderWidth:(CGFloat)width color:(UIColor *)color {
self.borderWidth = width;
self.borderColor = color;
}
#pragma mark - Kernel
/**
* @brief clip the cornerRadius with image, UIImageView must be setFrame before, no off-screen-rendered
*/
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
UIGraphicsBeginImageContextWithOptions(size, NO, scale);
if (nil == UIGraphicsGetCurrentContext()) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
[cornerPath addClip];
[image drawInRect:self.bounds];
[self drawBorder:cornerPath];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.image = processedImage;
}
/**
* @brief clip the cornerRadius with image, draw the backgroundColor you want, UIImageView must be setFrame before, no off-screen-rendered, no Color Blended layers
*/
- (void)zy_cornerRadiusWithImage:(UIImage *)image cornerRadius:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType backgroundColor:(UIColor *)backgroundColor {
CGSize size = self.bounds.size;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize cornerRadii = CGSizeMake(cornerRadius, cornerRadius);
UIGraphicsBeginImageContextWithOptions(size, YES, scale);
if (nil == UIGraphicsGetCurrentContext()) {
return;
}
UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds];
[backgroundColor setFill];
[backgroundRect fill];
[cornerPath addClip];
[image drawInRect:self.bounds];
[self drawBorder:cornerPath];
UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
objc_setAssociatedObject(processedImage, &kProcessedImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.image = processedImage;
}
/**
* @brief set cornerRadius for UIImageView, no off-screen-rendered
*/
- (void)zy_cornerRadiusAdvance:(CGFloat)cornerRadius rectCornerType:(UIRectCorner)rectCornerType {
self.radius = cornerRadius;
self.roundingCorners = rectCornerType;
self.isRounding = NO;
if (!self.hadAddObserver) {
[self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
self.hadAddObserver = YES;
}
}
/**
* @brief become Rounding UIImageView, no off-screen-rendered
*/
- (void)zy_cornerRadiusRoundingRect {
self.isRounding = YES;
if (!self.hadAddObserver) {
[self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
self.hadAddObserver = YES;
}
}
#pragma mark - Private
- (void)drawBorder:(UIBezierPath *)path {
if (0 != self.borderWidth && nil != self.borderColor) {
[path setLineWidth:2 * self.borderWidth];
[self.borderColor setStroke];
[path stroke];
}
}
- (void)dealloc {
if (self.hadAddObserver) {
[self removeObserver:self forKeyPath:@"image"];
}
}
- (void)validateFrame {
if (self.frame.size.width == 0) {
[self.class swizzleMethod:@selector(layoutSubviews) anotherMethod:@selector(zy_LayoutSubviews)];
}
}
+ (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method oneMethod = class_getInstanceMethod(self, oneSel);
Method anotherMethod = class_getInstanceMethod(self, anotherSel);
method_exchangeImplementations(oneMethod, anotherMethod);
});
}
- (void)zy_LayoutSubviews {
[super layoutSubviews];
if (self.isRounding) {
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.radius && 0 != self.roundingCorners && nil != self.image) {
[self zy_cornerRadiusWithImage:self.image cornerRadius:self.radius rectCornerType:self.roundingCorners];
}
}
#pragma mark - KVO for .image
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"image"]) {
UIImage *newImage = change[NSKeyValueChangeNewKey];
if ([newImage isMemberOfClass:[NSNull class]]) {
return;
} else if ([objc_getAssociatedObject(newImage, &kProcessedImage) intValue] == 1) {
return;
}
[self validateFrame];
if (self.isRounding) {
[self zy_cornerRadiusWithImage:newImage cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
} else if (0 != self.radius && 0 != self.roundingCorners && nil != self.image) {
[self zy_cornerRadiusWithImage:newImage cornerRadius:self.radius rectCornerType:self.roundingCorners];
}
}
}
#pragma mark property
- (CGFloat)borderWidth {
return [objc_getAssociatedObject(self, &kBorderWidth) floatValue];
}
- (void)setBorderWidth:(CGFloat)borderWidth {
objc_setAssociatedObject(self, &kBorderWidth, @(borderWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)borderColor {
return objc_getAssociatedObject(self, &kBorderColor);
}
- (void)setBorderColor:(UIColor *)borderColor {
objc_setAssociatedObject(self, &kBorderColor, borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)hadAddObserver {
return [objc_getAssociatedObject(self, &kHadAddObserver) boolValue];
}
- (void)setHadAddObserver:(BOOL)hadAddObserver {
objc_setAssociatedObject(self, &kHadAddObserver, @(hadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)isRounding {
return [objc_getAssociatedObject(self, &kIsRounding) boolValue];
}
- (void)setIsRounding:(BOOL)isRounding {
objc_setAssociatedObject(self, &kIsRounding, @(isRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIRectCorner)roundingCorners {
return [objc_getAssociatedObject(self, &kRoundingCorners) unsignedLongValue];
}
- (void)setRoundingCorners:(UIRectCorner)roundingCorners {
objc_setAssociatedObject(self, &kRoundingCorners, @(roundingCorners), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CGFloat)radius {
return [objc_getAssociatedObject(self, &kRadius) floatValue];
}
- (void)setRadius:(CGFloat)radius {
objc_setAssociatedObject(self, &kRadius, @(radius), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end