123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- //
- // UIImageView+CornerRadius.m
- // MyPractise
- //
- // Created by lzy on 16/3/1.
- // Copyright © 2016年 lzy. All rights reserved.
- //
- #import "UIImageView+CornerRadius.h"
- #import <objc/runtime.h>
- const char kProcessedImage;
- @interface UIImageView ()
- @property (assign, nonatomic) CGFloat zyRadius;
- @property (assign, nonatomic) UIRectCorner roundingCorners;
- @property (assign, nonatomic) CGFloat zyBorderWidth;
- @property (strong, nonatomic) UIColor *zyBorderColor;
- @property (assign, nonatomic) BOOL zyHadAddObserver;
- @property (assign, nonatomic) BOOL zyIsRounding;
- @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.zyBorderWidth = width;
- self.zyBorderColor = 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);
- CGContextRef currentContext = UIGraphicsGetCurrentContext();
- if (nil == currentContext) {
- return;
- }
- UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
- [cornerPath addClip];
- [self.layer renderInContext:currentContext];
- [self drawBorder:cornerPath];
- UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- if (processedImage) {
- 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);
- CGContextRef currentContext = UIGraphicsGetCurrentContext();
- if (nil == currentContext) {
- return;
- }
- UIBezierPath *cornerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCornerType cornerRadii:cornerRadii];
- UIBezierPath *backgroundRect = [UIBezierPath bezierPathWithRect:self.bounds];
- [backgroundColor setFill];
- [backgroundRect fill];
- [cornerPath addClip];
- [self.layer renderInContext:currentContext];
- [self drawBorder:cornerPath];
- UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- if (processedImage) {
- 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.zyRadius = cornerRadius;
- self.roundingCorners = rectCornerType;
- self.zyIsRounding = NO;
- if (!self.zyHadAddObserver) {
- [[self class] swizzleDealloc];
- [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
- self.zyHadAddObserver = YES;
- }
- //Xcode 8 xib 删除了控件的Frame信息,需要主动创造
- [self layoutIfNeeded];
- }
- /**
- * @brief become Rounding UIImageView, no off-screen-rendered
- */
- - (void)zy_cornerRadiusRoundingRect {
- self.zyIsRounding = YES;
- if (!self.zyHadAddObserver) {
- [[self class] swizzleDealloc];
- [self addObserver:self forKeyPath:@"image" options:NSKeyValueObservingOptionNew context:nil];
- self.zyHadAddObserver = YES;
- }
- //Xcode 8 xib 删除了控件的Frame信息,需要主动创造
- [self layoutIfNeeded];
- }
- #pragma mark - Private
- - (void)drawBorder:(UIBezierPath *)path {
- if (0 != self.zyBorderWidth && nil != self.zyBorderColor) {
- [path setLineWidth:2 * self.zyBorderWidth];
- [self.zyBorderColor setStroke];
- [path stroke];
- }
- }
- - (void)zy_dealloc {
- if (self.zyHadAddObserver) {
- [self removeObserver:self forKeyPath:@"image"];
- }
- [self zy_dealloc];
- }
- - (void)validateFrame {
- if (self.frame.size.width == 0) {
- [self.class swizzleLayoutSubviews];
- }
- }
- + (void)swizzleMethod:(SEL)oneSel anotherMethod:(SEL)anotherSel {
- Method oneMethod = class_getInstanceMethod(self, oneSel);
- Method anotherMethod = class_getInstanceMethod(self, anotherSel);
- method_exchangeImplementations(oneMethod, anotherMethod);
- }
- + (void)swizzleDealloc {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- [self swizzleMethod:NSSelectorFromString(@"dealloc") anotherMethod:@selector(zy_dealloc)];
- });
- }
- + (void)swizzleLayoutSubviews {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- [self swizzleMethod:@selector(layoutSubviews) anotherMethod:@selector(zy_LayoutSubviews)];
- });
- }
- - (void)zy_LayoutSubviews {
- [self zy_LayoutSubviews];
- if (self.zyIsRounding) {
- [self zy_cornerRadiusWithImage:self.image cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
- } else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) {
- [self zy_cornerRadiusWithImage:self.image cornerRadius:self.zyRadius 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.zyIsRounding) {
- [self zy_cornerRadiusWithImage:newImage cornerRadius:self.frame.size.width/2 rectCornerType:UIRectCornerAllCorners];
- } else if (0 != self.zyRadius && 0 != self.roundingCorners && nil != self.image) {
- [self zy_cornerRadiusWithImage:newImage cornerRadius:self.zyRadius rectCornerType:self.roundingCorners];
- }
- }
- }
- #pragma mark property
- - (CGFloat)zyBorderWidth {
- return [objc_getAssociatedObject(self, _cmd) floatValue];
- }
- - (void)setZyBorderWidth:(CGFloat)zyBorderWidth {
- objc_setAssociatedObject(self, @selector(zyBorderWidth), @(zyBorderWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (UIColor *)zyBorderColor {
- return objc_getAssociatedObject(self, _cmd);
- }
- - (void)setZyBorderColor:(UIColor *)zyBorderColor {
- objc_setAssociatedObject(self, @selector(zyBorderColor), zyBorderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (BOOL)zyHadAddObserver {
- return [objc_getAssociatedObject(self, _cmd) boolValue];
- }
- - (void)setZyHadAddObserver:(BOOL)zyHadAddObserver {
- objc_setAssociatedObject(self, @selector(zyHadAddObserver), @(zyHadAddObserver), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (BOOL)zyIsRounding {
- return [objc_getAssociatedObject(self, _cmd) boolValue];
- }
- - (void)setZyIsRounding:(BOOL)zyIsRounding {
- objc_setAssociatedObject(self, @selector(zyIsRounding), @(zyIsRounding), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (UIRectCorner)roundingCorners {
- return [objc_getAssociatedObject(self, _cmd) unsignedLongValue];
- }
- - (void)setRoundingCorners:(UIRectCorner)roundingCorners {
- objc_setAssociatedObject(self, @selector(roundingCorners), @(roundingCorners), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- - (CGFloat)zyRadius {
- return [objc_getAssociatedObject(self, _cmd) floatValue];
- }
- - (void)setZyRadius:(CGFloat)zyRadius {
- objc_setAssociatedObject(self, @selector(zyRadius), @(zyRadius), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- }
- @end
- //ZYCornerRadius is available under the MIT license.
- //Please visit https://github.com/liuzhiyi1992/ZYCornerRadius for details.
|