UIView+ConerRadius.m 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // UIView+ConerRadius.m
  3. // sansanMassage_Consumer
  4. //
  5. // Created by YoMi on 2022/8/11.
  6. //
  7. #import "UIView+ConerRadius.h"
  8. #import "NSObject+Swizzle.h"
  9. #import <objc/runtime.h>
  10. @interface YMCornerRadiusModel : NSObject
  11. @property (nonatomic, assign) CGFloat radius;
  12. @property (nonatomic, assign) UIRectCorner corners;
  13. @property (nonatomic, assign) UIEdgeInsets inserts;
  14. @end
  15. @implementation YMCornerRadiusModel
  16. + (instancetype)modelWithRadius:(CGFloat)radius corners:(UIRectCorner)corners insets:(UIEdgeInsets)inserts {
  17. YMCornerRadiusModel *model = [[YMCornerRadiusModel alloc] init];
  18. model.corners = corners;
  19. model.radius = radius;
  20. model.inserts = inserts;
  21. return model;
  22. }
  23. @end
  24. static void *ym_cornerRadiusMaskKey = &ym_cornerRadiusMaskKey;
  25. @implementation UIView (ConerRadius)
  26. + (void)load {
  27. static dispatch_once_t onceToken;
  28. dispatch_once(&onceToken, ^{
  29. [self swizzleOriginalSelector:@selector(layoutSubviews) swizzleSelector:@selector(ym_layoutSubviews) isInstanceSelector:YES];
  30. });
  31. }
  32. - (void)addRectCorner:(UIRectCorner)corners radius:(CGFloat)radius {
  33. [self addRectCorner:corners radius:radius insets:UIEdgeInsetsZero];
  34. }
  35. - (void)addRectCorner:(UIRectCorner)corners radius:(CGFloat)radius insets:(UIEdgeInsets)inserts {
  36. // 如果是这两个情况则直接移除圆角化
  37. if ((corners == 0 || radius <= 0) && UIEdgeInsetsEqualToEdgeInsets(inserts, UIEdgeInsetsZero)) {
  38. [self removeCornerRadius];
  39. return;
  40. }
  41. YMCornerRadiusModel *oldModel = [self ym_cornerRadius];
  42. // 判断是否跟旧的圆角化数据一样
  43. if (oldModel.corners == corners && oldModel.radius == radius && UIEdgeInsetsEqualToEdgeInsets(oldModel.inserts, inserts)) return;
  44. YMCornerRadiusModel *model = [YMCornerRadiusModel modelWithRadius:radius corners:corners insets:inserts];
  45. objc_setAssociatedObject(self, ym_cornerRadiusMaskKey, model, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  46. [self updateCornerMaskLayer];
  47. }
  48. - (void)removeCornerRadius {
  49. [self viewForMakeCornerRadius].layer.mask = nil;
  50. objc_setAssociatedObject(self, ym_cornerRadiusMaskKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  51. [self updateCornerMaskLayer];
  52. }
  53. - (YMCornerRadiusModel *)ym_cornerRadius {
  54. return objc_getAssociatedObject(self, ym_cornerRadiusMaskKey);
  55. }
  56. - (void)ym_layoutSubviews {
  57. [self ym_layoutSubviews];
  58. YMCornerRadiusModel *cornerModel = [self ym_cornerRadius];
  59. if (cornerModel != nil) {
  60. [self updateCornerMaskLayer];
  61. }
  62. }
  63. - (CAShapeLayer *)maskLayerForModel:(YMCornerRadiusModel *)model {
  64. if (model == nil) return nil;
  65. CGRect bounds = self.bounds;
  66. bounds.size.width -= model.inserts.left + model.inserts.right;
  67. bounds.size.height -= model.inserts.top + model.inserts.bottom;
  68. UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:model.corners cornerRadii:CGSizeMake(model.radius, model.radius)];
  69. CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
  70. maskLayer.frame = CGRectMake(model.inserts.left, model.inserts.top, bounds.size.width, bounds.size.height);
  71. maskLayer.path = maskPath.CGPath;
  72. return maskLayer;
  73. }
  74. - (void)updateCornerMaskLayer {
  75. self.layer.mask = [self maskLayerForModel:[self ym_cornerRadius]];
  76. }
  77. - (UIView *)viewForMakeCornerRadius {
  78. return self;
  79. }
  80. @end