You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

391 lines
14 KiB

//
// UIView+Effects.m
// CCViewEffects
//
// Created by 佰道聚合 on 2017/9/8.
// Copyright © 2017年 cyd. All rights reserved.
//
#import "UIView+Effects.h"
#import <objc/runtime.h>
#define kConrnerCorner "UIView.privateConrnerCorner"
#define kConrnerBounds "UIView.privateConrnerBounds"
#define kConrnerRadius "UIView.privateConrnerRadius"
#define kBorderColor "UIView.privateBorderColor"
#define kBorderWidth "UIView.privateBorderWidth"
#define kShadowOpacity "UIView.privateShadowOpacity"
#define kShadowRadius "UIView.privateShadowRadius"
#define kShadowOffset "UIView.privateShadowOffset"
#define kShadowColor "UIView.privateShadowColor"
#define kBezierPath "UIView.privateBezierPath"
#define kViewBounds "UIView.privateViewBounds"
#define kBackgroundView "UIView.BackgroundView"
@implementation UIView (Effects)
@dynamic conrnerCorner,
conrnerRadius,
borderColor,
borderWidth,
shadowColor,
shadowOffset,
shadowRadius,
shadowOpacity,
showVisual,
clerVisual,
bezierPath,
viewBounds;
#pragma mark - 添加私有属性
// mark - 圆角 矩形 默认 AllCorners
- (void)setPrivateConrnerCorner:(UIRectCorner)corner {
objc_setAssociatedObject(self, kConrnerCorner, [NSNumber numberWithInteger:corner], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (UIRectCorner)privateConrnerCorner {
id corner = objc_getAssociatedObject(self, kConrnerCorner);
return corner ? [corner integerValue] : UIRectCornerAllCorners;
}
// mark - 圆角 半径 默认 0.0
- (void)setPrivateConrnerRadius:(CGFloat)radius {
objc_setAssociatedObject(self, kConrnerRadius, [NSNumber numberWithFloat:radius], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGFloat)privateConrnerRadius {
id radius = objc_getAssociatedObject(self, kConrnerRadius);
return radius ? [radius floatValue] : 0.0;
}
// mark - 边框 宽度 默认 0.0
- (void)setPrivateBorderWidth:(CGFloat)width {
objc_setAssociatedObject(self, kBorderWidth, [NSNumber numberWithFloat:width], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGFloat)privateBorderWidth {
id width = objc_getAssociatedObject(self, kBorderWidth);
return width ? [width floatValue] : 0.0;
}
// mark - 边框 颜色 默认 黑色
- (void)setPrivateBorderColor:(UIColor *)color {
objc_setAssociatedObject(self, kBorderColor, color, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (UIColor *)privateBorderColor {
id color = objc_getAssociatedObject(self, kBorderColor);
return color ? color : [UIColor blackColor];
}
// mark - 阴影 半径 默认 0.0
- (void)setPrivateShadowRadius:(CGFloat)opacity {
objc_setAssociatedObject(self, kShadowOpacity, [NSNumber numberWithFloat:opacity], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGFloat)privateShadowRadius {
id radius = objc_getAssociatedObject(self, kShadowOpacity);
return radius ? [radius floatValue] : 0.0;
}
// mark - 阴影 模糊度 默认 0.0
- (void)setPrivateShadowOpacity:(CGFloat)radius {
objc_setAssociatedObject(self, kShadowRadius, [NSNumber numberWithFloat:radius], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGFloat)privateShadowOpacity {
id opacity = objc_getAssociatedObject(self, kShadowRadius);
return opacity ? [opacity floatValue] : 0.0;
}
// mark - 阴影 偏移方向和距离 默认 {0.0,0.0}
- (void)setPrivateShadowOffset:(CGSize)offset {
objc_setAssociatedObject(self, kShadowOffset, NSStringFromCGSize(offset), OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGSize)privateShadowOffset {
id offset = objc_getAssociatedObject(self, kShadowOffset);
return offset ? CGSizeFromString(offset) : CGSizeZero;
}
// mark - 阴影 颜色 默认 black
- (void)setPrivateShadowColor:(UIColor *)color {
objc_setAssociatedObject(self, kShadowColor, color, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (UIColor *)privateShadowColor {
id color = objc_getAssociatedObject(self, kShadowColor);
return color ? color : [UIColor blackColor];
}
// mark - 路径 默认 nil
- (void)setPrivateBezierPath:(UIBezierPath *)path {
objc_setAssociatedObject(self, kBezierPath, path, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (UIBezierPath *)privateBezierPath {
id path = objc_getAssociatedObject(self, kBezierPath);
return path ? path : nil;
}
// mark - 视图 大小 默认 nil
- (void)setPrivateViewBounds:(CGRect)rect {
objc_setAssociatedObject(self, kViewBounds, NSStringFromCGRect(rect), OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGRect)privateViewBounds {
id path = objc_getAssociatedObject(self, kViewBounds);
return path ? CGRectFromString(path) : CGRectZero;
}
// 阴影空视图,只在有圆角的时候使用
- (UIView *)shadowBackgroundView {
return objc_getAssociatedObject(self, kBackgroundView);
}
- (void)setShadowBackgroundView:(UIView *)backgroundView {
objc_setAssociatedObject(self, kBackgroundView, backgroundView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#pragma mark - 链式属性实现
- (ConrnerCorner)conrnerCorner {
return ^(UIRectCorner corner) {
self.privateConrnerCorner = corner;
return self;
};
}
- (ConrnerRadius)conrnerRadius {
return ^(CGFloat radius) {
self.privateConrnerRadius = radius;
return self;
};
}
- (BorderColor)borderColor {
return ^(UIColor *color) {
self.privateBorderColor = color;
return self;
};
}
- (BorderWidth)borderWidth {
return ^(CGFloat width) {
self.privateBorderWidth = width;
return self;
};
}
- (ShadowOpacity)shadowOpacity {
return ^(CGFloat opacity) {
self.privateShadowOpacity = opacity;
return self;
};
}
- (ShadowRadius)shadowRadius {
return ^(CGFloat radius) {
self.privateShadowRadius = radius;
return self;
};
}
- (ShadowOffset)shadowOffset {
return ^(CGSize size) {
self.privateShadowOffset = size;
return self;
};
}
- (ShadowColor)shadowColor {
return ^(UIColor *color) {
self.privateShadowColor = color;
return self;
};
}
- (BezierPath)bezierPath {
return ^(UIBezierPath *path) {
self.privateBezierPath = path;
return self;
};
}
- (ViewBounds)viewBounds {
return ^(CGRect rect) {
self.privateViewBounds = rect;
return self;
};
}
#pragma mark - 方法实现
- (ClerVisual)clerVisual {
return ^{
// 阴影
if (self.shadowBackgroundView) {
[self.shadowBackgroundView removeFromSuperview];
self.shadowBackgroundView = nil;
}
// 圆角、边框
for (CALayer *layer in self.layer.sublayers) {
if ([layer.name isEqualToString:@"CCViewEffects"]) {
[layer removeFromSuperlayer];
}
}
// 恢复默认设置
self.privateConrnerCorner = UIRectCornerAllCorners;
self.privateConrnerRadius = 0.0;
self.privateBorderColor = [UIColor blackColor];
self.privateBorderWidth = 0.0;
self.privateShadowOpacity = 0.0;
self.privateShadowRadius = 0.0;
self.privateShadowOffset = CGSizeZero;
self.privateViewBounds = CGRectZero;
self.privateShadowColor = [UIColor blackColor];
self.shadowBackgroundView = nil;
self.layer.masksToBounds = NO;
self.layer.cornerRadius = 0.0;
self.layer.borderWidth = 0.0;
self.layer.borderColor = [UIColor blackColor].CGColor;
self.layer.shadowOpacity = 0.0;
self.layer.shadowPath = nil;
self.layer.shadowRadius = 0.0;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeZero;
self.layer.mask = nil;
return self;
};
}
- (ShowVisual)showVisual {
return ^{
// 阴影
[self addShadow];
// 边框、圆角
[self addBorderAndRadius];
return self;
};
}
#pragma mark - Private methods
-(CGRect)drawBounds {
// 1.如果传入了大小,则直接返回
if (!CGRectEqualToRect(self.privateViewBounds, CGRectZero)) {
return self.privateViewBounds;
}
// 2.获取在自动布局时的视图大小
if (self.superview != nil) {
[self.superview layoutIfNeeded];
}
return self.bounds;
}
-(UIBezierPath *)drawBezierPath {
if (self.privateBezierPath != nil) {
return self.privateBezierPath;
}
return [UIBezierPath bezierPathWithRoundedRect:[self drawBounds]
byRoundingCorners:self.privateConrnerCorner
cornerRadii:CGSizeMake(self.privateConrnerRadius, self.privateConrnerRadius)];
}
// 添加阴影
-(void)addShadow {
UIView *shadowView = self;
// 同时存在阴影和圆角
if ((self.privateShadowOpacity > 0 && self.privateConrnerRadius > 0) || self.privateBezierPath) {
if (self.shadowBackgroundView) {
[self.shadowBackgroundView removeFromSuperview];
self.shadowBackgroundView = nil;
}
NSAssert(self.superview, @"添加阴影和圆角时,请先将view加到父视图上");
shadowView = [[UIView alloc] initWithFrame:self.frame];
shadowView.translatesAutoresizingMaskIntoConstraints = NO;
[self.superview insertSubview:shadowView belowSubview:self];
[self.superview addConstraints:@[[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0],
[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0],
[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0],
[NSLayoutConstraint constraintWithItem:shadowView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0]]];
self.shadowBackgroundView = shadowView;
}
// 圆角
if (self.privateConrnerRadius > 0 || self.privateBezierPath) {
UIBezierPath *shadowPath = [self drawBezierPath];
shadowView.layer.shadowPath = shadowPath.CGPath;
}
// 阴影
shadowView.layer.masksToBounds = NO;
shadowView.layer.shadowOpacity = self.privateShadowOpacity;
shadowView.layer.shadowRadius = self.privateShadowRadius;
shadowView.layer.shadowOffset = self.privateShadowOffset;
shadowView.layer.shadowColor = self.privateShadowColor.CGColor;
}
// 添加圆角和边框
-(void)addBorderAndRadius {
// 圆角或阴影或自定义曲线
if (self.privateConrnerRadius > 0 || self.privateShadowOpacity > 0 || self.privateBezierPath) {
// 圆角
if (self.privateConrnerRadius > 0 || self.privateBezierPath) {
UIBezierPath *path = [self drawBezierPath];
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
maskLayer.path = path.CGPath;
self.layer.mask = maskLayer;
}
// 边框
if (self.privateBorderWidth > 0 || self.privateBezierPath) {
for (CALayer *layer in self.layer.sublayers) {
if ([layer.name isEqualToString:@"CCViewEffects"]) {
[layer removeFromSuperlayer];
}
}
UIBezierPath *path = [self drawBezierPath];
CAShapeLayer *layer = [[CAShapeLayer alloc]init];
layer.name = @"CCViewEffects";
layer.frame = self.bounds;
layer.path = path.CGPath;
layer.lineWidth = self.privateBorderWidth;
layer.strokeColor = self.privateBorderColor.CGColor;
layer.fillColor = [UIColor clearColor].CGColor;
[self.layer addSublayer:layer];
}
} else {
// 只有边框
self.layer.masksToBounds = true;
self.layer.borderWidth = self.privateBorderWidth;
self.layer.borderColor = self.privateBorderColor.CGColor;
}
}
@end