Files
featherVoice/QXLive/Tools/Category/UIView+QX.m
2025-08-08 10:49:36 +08:00

509 lines
18 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// UIView+QX.m
// QXLive
//
// Created by 启星 on 2025/4/27.
//
#import "UIView+QX.h"
static const void* tagValue = &tagValue;
@implementation UIView (QX)
- (void)setX:(CGFloat)x {
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (void)setY:(CGFloat)y {
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
- (CGFloat)x {
return self.frame.origin.x;
}
- (CGFloat)y {
return self.frame.origin.y;
}
- (void)setCenterX:(CGFloat)centerX {
CGPoint center = self.center;
center.x = centerX;
self.center = center;
}
- (CGFloat)centerX {
return self.center.x;
}
- (void)setCenterY:(CGFloat)centerY{
CGPoint center = self.center;
center.y = centerY;
self.center = center;
}
- (CGFloat)centerY {
return self.center.y;
}
- (void)setWidth:(CGFloat)width {
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (void)setHeight:(CGFloat)height {
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (CGFloat)height {
return self.frame.size.height;
}
- (CGFloat)width {
return self.frame.size.width;
}
- (void)setSize:(CGSize)size {
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
- (CGSize)size {
return self.frame.size;
}
- (void)setOrigin:(CGPoint)origin {
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}
- (CGPoint)origin {
return self.frame.origin;
}
- (CGFloat)top {
return self.frame.origin.y;
}
- (void)setTop:(CGFloat)top {
CGRect frame = self.frame;
frame.origin.y = top;
self.frame = frame;
}
- (CGFloat)left {
return self.frame.origin.x;
}
- (void)setLeft:(CGFloat)left {
CGRect frame = self.frame;
frame.origin.x = left;
self.frame = frame;
}
- (CGFloat)bottom {
return self.frame.size.height + self.frame.origin.y;
}
- (void)setBottom:(CGFloat)bottom {
CGRect frame = self.frame;
frame.origin.y = bottom - frame.size.height;
self.frame = frame;
}
- (CGFloat)right {
return self.frame.size.width + self.frame.origin.x;
}
- (void)setRight:(CGFloat)right {
CGRect frame = self.frame;
frame.origin.x = right - frame.size.width;
self.frame = frame;
}
#pragma mark - 快速添加阴影
- (void)addProjectionWithShadowOpacity:(CGFloat)shadowOpacity {
self.layer.shadowColor = [UIColor blackColor].CGColor;//shadowColor阴影颜色
self.layer.shadowOffset = CGSizeMake(0,0);//shadowOffset阴影偏移,x向右偏移2y向下偏移6默认(0, -3),这个跟shadowRadius配合使用
self.layer.shadowOpacity = shadowOpacity;//阴影透明度默认0
self.layer.shadowRadius = 3;//阴影半径默认3
}
- (void)addShadowWithColor:(UIColor*)color radius:(CGFloat)radius{
CALayer *subLayer = [CALayer layer];
subLayer.frame = self.frame;
subLayer.cornerRadius = radius;
subLayer.masksToBounds = NO;
subLayer.backgroundColor = color.CGColor;
subLayer.shadowColor = color.CGColor;//shadowColor阴影颜色
subLayer.shadowOffset = CGSizeMake(0,2);
subLayer.shadowOpacity = 0.5;//阴影透明度默认0
subLayer.shadowRadius = radius;//阴影半径默认3
[self.layer insertSublayer:subLayer below:self.layer];
}
- (void)addShadowWithColor:(UIColor*)color radius:(CGFloat)radius frame:(CGRect)frame{
CALayer *subLayer = [CALayer layer];
subLayer.frame = frame;
subLayer.cornerRadius = radius;
subLayer.masksToBounds = YES;
subLayer.backgroundColor = color.CGColor;
subLayer.shadowColor = color.CGColor;//shadowColor阴影颜色
subLayer.shadowOffset = CGSizeMake(0,-3);
subLayer.shadowOpacity = 0.5;//阴影透明度默认0
subLayer.shadowRadius = radius;//阴影半径默认3
[self.layer insertSublayer:subLayer below:self.layer];
}
- (void)addBorderWithWidth:(CGFloat)width {
self.layer.borderWidth = width;
self.layer.borderColor = [UIColor blackColor].CGColor;
}
- (void)addBorderWithWidth:(CGFloat)width borderColor:(UIColor *)borderColor {
self.layer.borderWidth = width;
self.layer.borderColor = borderColor.CGColor;
}
- (void)addRoundedCornersWithRadius:(CGFloat)radius {
self.layer.cornerRadius = radius;
self.layer.masksToBounds = YES;
}
- (void)addRoundedCornersWithRadius:(CGFloat)radius byRoundingCorners:(UIRectCorner)corners{
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setTopToBottomGradientBackgroundWithColors:(NSArray<UIColor *> *)colors {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1)];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5)];
}
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = startPoint;
gradientLayer.endPoint = endPoint;
gradientLayer.frame = self.bounds;
// [self.layer addSublayer:gradientLayer];
//layout中重复添加CAGradientLayer需要清空多余的渐变层
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors roundedCorners:(CGFloat)radius {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
gradientLayer.frame = self.bounds;
gradientLayer.cornerRadius = radius;
gradientLayer.masksToBounds = YES;
//layout中重复添加CAGradientLayer需要清空多余的渐变层
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setAroundRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setTopRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setBottomRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setLeftRoundedCorners:(CGFloat)radius {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
#pragma mark - 按Frame计算
- (void)setTopToBottomGradientBackgroundWithColors:(NSArray<UIColor *> *)colors frame:(CGRect)frame {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1) frame:frame];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors frame:(CGRect)frame {
[self setGradientBackgroundWithColors:colors startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5) frame:frame];
}
- (void)setGradientBackgroundWithColors:(NSArray<UIColor *> *)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint frame:(CGRect)frame {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = startPoint;
gradientLayer.endPoint = endPoint;
gradientLayer.frame = frame;
// [self.layer addSublayer:gradientLayer];
//layout中重复添加CAGradientLayer需要清空多余的渐变层
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setLeftToRightGradientBackgroundWithColors:(NSArray<UIColor *> *)colors roundedCorners:(CGFloat)radius frame:(CGRect)frame {
NSMutableArray *colorsM = [NSMutableArray array];
for (UIColor *color in colors) {
[colorsM addObject:(__bridge id)color.CGColor];
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colorsM;
gradientLayer.locations = @[@0, @1];
gradientLayer.startPoint = CGPointMake(0, 0.5);
gradientLayer.endPoint = CGPointMake(1, 0.5);
gradientLayer.frame = frame;
gradientLayer.cornerRadius = radius;
gradientLayer.masksToBounds = YES;
//layout中重复添加CAGradientLayer需要清空多余的渐变层
NSArray<CALayer *> *subLayers = self.layer.sublayers;
NSArray<CALayer *> *removedLayers = [subLayers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[CAGradientLayer class]];
}]];
[removedLayers enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj removeFromSuperlayer];
}];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
- (void)setAroundRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setTopRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setBottomRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setLeftRoundedCorners:(CGFloat)radius frame:(CGRect)frame {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:UIRectCornerTopLeft | UIRectCornerBottomLeft cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = frame;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)setViewShadowPathWithColor:(UIColor *)shadowColor shadowOpacity:(CGFloat)shadowOpacity shadowRadius:(CGFloat)shadowRadius shadowPathType:(ShadowPathType)shadowPathType shadowPathWidth:(CGFloat)shadowPathWidth {
self.layer.masksToBounds = NO;//必须要等于NO否则会把阴影切割隐藏掉
self.layer.shadowColor = shadowColor.CGColor;// 阴影颜色
self.layer.shadowOpacity = shadowOpacity;// 阴影透明度默认0
self.layer.shadowOffset = CGSizeZero;//shadowOffset阴影偏移默认(0, -3),这个跟shadowRadius配合使用
self.layer.shadowRadius = shadowRadius;//阴影半径默认3
CGRect shadowRect = CGRectZero;
CGFloat originX,originY,sizeWith,sizeHeight;
originX = 0;
originY = 0;
sizeWith = self.bounds.size.width;
sizeHeight = self.bounds.size.height;
if (shadowPathType == ShadowPathTop) {
shadowRect = CGRectMake(originX, originY-shadowPathWidth/2, sizeWith, shadowPathWidth);
}else if (shadowPathType == ShadowPathBottom){
shadowRect = CGRectMake(originY, sizeHeight-shadowPathWidth/2, sizeWith, shadowPathWidth);
}else if (shadowPathType == ShadowPathLeft){
shadowRect = CGRectMake(originX-shadowPathWidth/2, originY, shadowPathWidth, sizeHeight);
}else if (shadowPathType == ShadowPathRight){
shadowRect = CGRectMake(sizeWith-shadowPathWidth/2, originY, shadowPathWidth, sizeHeight);
}else if (shadowPathType == ShadowPathCommon){
shadowRect = CGRectMake(originX-shadowPathWidth/2, 2, sizeWith+shadowPathWidth, sizeHeight+shadowPathWidth/2);
}else if (shadowPathType == ShadowPathAround){
shadowRect = CGRectMake(originX-shadowPathWidth/2, originY-shadowPathWidth/2, sizeWith+shadowPathWidth, sizeHeight+shadowPathWidth);
}
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:shadowRect];
self.layer.shadowPath = bezierPath.CGPath;//阴影路径
}
- (void)setViewBackgroundColorWithColorArray:(NSArray *)colorArray scaleArray:(NSArray * __nullable)scaleArray direction:(SRGradientDirection)direction {
/*
layoutIfNeeded不一定会调用layoutSubviews方法。
setNeedsLayout一定会调用layoutSubviews方法有延迟在下一轮runloop结束前
如果想在当前runloop中立即刷新调用顺序应该是:
[self setNeedsLayout];
[self layoutIfNeeded];
*/
[self setNeedsLayout];
[self layoutIfNeeded];
CAGradientLayer *gradinentlayer = [CAGradientLayer layer];
if (direction == SRGradientDirectionLeftToRight) {
gradinentlayer.startPoint = CGPointMake(0, 0);
gradinentlayer.endPoint = CGPointMake(1.0, 0);
}else {
gradinentlayer.startPoint = CGPointMake(0, 0);
gradinentlayer.endPoint = CGPointMake(0, 1.0);
}
NSMutableArray *CGColorArray = [NSMutableArray new];
for (UIColor *color in colorArray) {
[CGColorArray addObject:(__bridge id)color.CGColor];
}
if (!scaleArray) {
}else {
gradinentlayer.locations = scaleArray;
}
gradinentlayer.colors = CGColorArray;
gradinentlayer.frame = self.bounds;
[self.layer addSublayer:gradinentlayer];
}
- (void)tap{
if (self.tapAction) {
self.tapAction(self);
}
}
- (void)addTapBlock:(void(^)(id obj))tapAction{
self.tapAction = tapAction;
if (![self gestureRecognizers]) {
self.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
[self addGestureRecognizer:tap];
}
}
-(void)setTapAction:(void (^)(id))tapAction {
objc_setAssociatedObject(self, tagValue, tapAction, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(void (^)(id))tapAction {
return objc_getAssociatedObject(self, tagValue);
}
- (UIViewController *)viewController {
id nextResponder = [self nextResponder];
while (nextResponder != nil) {
if ([nextResponder isKindOfClass:[UIViewController class]]) {
UIViewController *vc = (UIViewController *)nextResponder;
return vc;
}
nextResponder = [nextResponder nextResponder];
}
return nil;
}
- (UINavigationController *)navigationController {
id nextResponder = [self nextResponder];
while (nextResponder != nil) {
if ([nextResponder isKindOfClass:[UINavigationController class]]) {
UINavigationController *vc = (UINavigationController *)nextResponder;
return vc;
}
nextResponder = [nextResponder nextResponder];
}
return nil;
}
@end