Newer
Older
XinYang_IOS / YH_Category / UIView+RITLBorder.m
@zhangfeng zhangfeng on 7 Dec 2023 9 KB 1.8.0
//
//  UIView+RITLBorder.m
//  RITLBorder
//
//  Created by YueWen on 2018/1/11.
//  Copyright © 2018年 YueWen. All rights reserved.
//

#import "UIView+RITLBorder.h"
#import <Foundation/Foundation.h>
#import <objc/runtime.h>

#pragma mark - RITLBorderLayer

@interface RITLBorderLayer: CALayer

/// 默认为0.0
@property (nonatomic, assign)CGFloat ritl_borderWidth;
/// 默认为UIEdgeInsetsZero
@property (nonatomic, assign)UIEdgeInsets ritl_borderInset;

@end

@implementation RITLBorderLayer

- (instancetype)init
{
    if (self = [super init]) {
        
        self.anchorPoint = CGPointZero;
        self.ritl_borderWidth = 1;
        self.ritl_borderInset = UIEdgeInsetsZero;
    }
    
    return self;
}

@end


#pragma mark - <RITLViewBorderDirection>

@protocol RITLViewBorderDirection <NSObject>

@property (nonatomic, strong) RITLBorderLayer *leftLayer;
@property (nonatomic, strong) RITLBorderLayer *topLayer;
@property (nonatomic, strong) RITLBorderLayer *rightLayer;
@property (nonatomic, strong) RITLBorderLayer *bottomLayer;

@end



#pragma mark - UIView<RITLViewBorderDirection>
@interface UIView (RITLViewBorderDirection)<RITLViewBorderDirection>
@end


#pragma mark - UIView(RITLBorder)
@implementation UIView (RITLBorder)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        Method originMethod = class_getInstanceMethod(self, @selector(layoutSubviews));
        Method swizzledMethod = class_getInstanceMethod(self, @selector(ritl_borderlayoutsubViews));
        
        BOOL didAddMethod = class_addMethod(self, @selector(layoutSubviews), method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        
        if (didAddMethod) {//追加成功,进行替换
            
            class_replaceMethod(self,
                                @selector(layoutSubviews),
                                method_getImplementation(swizzledMethod),
                                method_getTypeEncoding(swizzledMethod));
        }else {
            
            method_exchangeImplementations(originMethod, swizzledMethod);
        }
    });
}



- (void)ritl_borderlayoutsubViews
{
    [self ritl_borderlayoutsubViews];

    CGRect generalBound = self.leftLayer.bounds;
    CGPoint generalPoint = CGPointZero;
    UIEdgeInsets generalInset = self.leftLayer.ritl_borderInset;
    
    //left
    generalBound.size.height = self.layer.bounds.size.height - generalInset.top - generalInset.bottom+2;//高度
    generalBound.size.width = self.leftLayer.ritl_borderWidth;//宽度为border
    self.leftLayer.bounds = generalBound;
    
    generalPoint.x = generalInset.left;
    generalPoint.y = generalInset.top-1;
    self.leftLayer.position = generalPoint;
    
    generalBound = self.topLayer.bounds;
    generalPoint = self.topLayer.position;
    generalInset = self.topLayer.ritl_borderInset;
    
    //top
    generalBound.size.height = self.topLayer.ritl_borderWidth;
    generalBound.size.width = self.layer.bounds.size.width - generalInset.left - generalInset.right;
    self.topLayer.bounds = generalBound;
    
    generalPoint.x = generalInset.left;
    generalPoint.y = generalInset.top;
    self.topLayer.position = generalPoint;
    
    generalBound = self.rightLayer.bounds;
    generalPoint = self.rightLayer.position;
    generalInset = self.rightLayer.ritl_borderInset;
    
    //right
    generalBound.size.height = self.layer.bounds.size.height - generalInset.top - generalInset.bottom;
    generalBound.size.width = self.rightLayer.ritl_borderWidth;
    self.rightLayer.bounds = generalBound;
    
    generalPoint.x = self.layer.bounds.size.width - generalInset.right - generalBound.size.width;
    generalPoint.y = generalInset.top;
    self.rightLayer.position = generalPoint;
    
    generalBound = self.bottomLayer.bounds;
    generalPoint = self.bottomLayer.position;
    generalInset = self.bottomLayer.ritl_borderInset;
    
    //bottom
    generalBound.size.height = self.bottomLayer.ritl_borderWidth;
    generalBound.size.width = self.layer.bounds.size.width - generalInset.right - generalInset.left;
    self.bottomLayer.bounds = generalBound;
    
    generalPoint.x = generalInset.left;
    generalPoint.y = self.layer.bounds.size.height - generalInset.bottom - generalBound.size.height;
    self.bottomLayer.position = generalPoint;
}





#pragma mark - public

- (void)ritl_addBorderWithInset:(UIEdgeInsets)inset
                          Color:(UIColor *)borderColor
                      direction:(RITLBorderDirection)directions
{
    [self ritl_addBorderWithInset:inset Color:borderColor BorderWidth:self.layer.borderWidth direction:directions];
}


- (void)ritl_addBorderWithInset:(UIEdgeInsets)inset
                    BorderWidth:(CGFloat)borderWidth
                      direction:(RITLBorderDirection)directions
{
    [self ritl_addBorderWithInset:inset Color:[UIColor colorWithCGColor:self.layer.borderColor] BorderWidth:borderWidth direction:directions];
}


- (void)ritl_addBorderWithColor:(UIColor *)borderColor
                    BodrerWidth:(CGFloat)borderWidth
                      direction:(RITLBorderDirection)directions
{
    [self ritl_addBorderWithInset:UIEdgeInsetsZero Color:borderColor BorderWidth:borderWidth direction:directions];
}


- (void)ritl_addBorderWithInset:(UIEdgeInsets)inset
                          Color:(UIColor *)borderColor
                    BorderWidth:(CGFloat)borderWidth
                      direction:(RITLBorderDirection)directions
{
    if (directions & RITLBorderDirectionLeft) {
        
        self.leftLayer.backgroundColor = borderColor.CGColor;
        self.leftLayer.ritl_borderWidth = borderWidth;
        self.leftLayer.ritl_borderInset = inset;
        if (self.leftLayer.superlayer) { [self.leftLayer removeFromSuperlayer]; }
        [self.layer addSublayer:self.leftLayer];
    }
    
    if (directions & RITLBorderDirectionTop) {
        
        self.topLayer.backgroundColor = borderColor.CGColor;
        self.topLayer.ritl_borderWidth = borderWidth;
        self.topLayer.ritl_borderInset = inset;
        if (self.topLayer.superlayer) { [self.topLayer removeFromSuperlayer]; }
        [self.layer addSublayer:self.topLayer];
    }
    
    if (directions & RITLBorderDirectionRight) {
        
        self.rightLayer.backgroundColor = borderColor.CGColor;
        self.rightLayer.ritl_borderWidth = borderWidth;
        self.rightLayer.ritl_borderInset = inset;
        if (self.rightLayer.superlayer) { [self.rightLayer removeFromSuperlayer]; }
        [self.layer addSublayer:self.rightLayer];
    }
    
    if (directions & RITLBorderDirectionBottom) {
        
        self.bottomLayer.backgroundColor = borderColor.CGColor;
        self.bottomLayer.ritl_borderWidth = borderWidth;
        self.bottomLayer.ritl_borderInset = inset;
        if (self.bottomLayer.superlayer) { [self.bottomLayer removeFromSuperlayer]; }
        [self.layer addSublayer:self.bottomLayer];
    }
    
    [self setNeedsLayout];
}



- (void)ritl_removeBorders:(RITLBorderDirection)directions
{
    if (directions & RITLBorderDirectionLeft) {
        
        [self ritl_removeBorderLayer:self.leftLayer];
    }
    
    if (directions & RITLBorderDirectionTop) {
        
        [self ritl_removeBorderLayer:self.topLayer];
    }
    
    if (directions & RITLBorderDirectionRight) {
        
        [self ritl_removeBorderLayer:self.rightLayer];
    }
    
    if (directions & RITLBorderDirectionBottom) {
        
        [self ritl_removeBorderLayer:self.bottomLayer];
    }
}

- (void)ritl_removeAllBorders
{
    [self ritl_removeBorderLayer:self.leftLayer];
    [self ritl_removeBorderLayer:self.topLayer];
    [self ritl_removeBorderLayer:self.rightLayer];
    [self ritl_removeBorderLayer:self.bottomLayer];
}



#pragma mark - private

- (void)ritl_removeBorderLayer:(CALayer *)layer
{
    if (layer) {
        
        [layer removeFromSuperlayer];
    }
}

//
//- (BOOL)ritl_checkLayer:(CALayer *)layer
//{
//    return layer.superlayer;
//}


#pragma mark - RITLViewBorderDirection


#pragma mark - layer

- (void)setLeftLayer:(RITLBorderLayer *)leftLayer
{
    objc_setAssociatedObject(self, @selector(leftLayer), leftLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)setTopLayer:(RITLBorderLayer *)topLayer
{
    objc_setAssociatedObject(self, @selector(topLayer), topLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)setRightLayer:(RITLBorderLayer *)rightLayer
{
    objc_setAssociatedObject(self, @selector(rightLayer), rightLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)setBottomLayer:(RITLBorderLayer *)bottomLayer
{
    objc_setAssociatedObject(self, @selector(bottomLayer), bottomLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


- (RITLBorderLayer *)leftLayer
{
    id layer = objc_getAssociatedObject(self, _cmd);

    if (layer == nil) {

        self.leftLayer = RITLBorderLayer.new;
    }

    return objc_getAssociatedObject(self, _cmd);
}


- (RITLBorderLayer *)topLayer
{
    id layer = objc_getAssociatedObject(self, _cmd);

    if (layer == nil) {

        self.topLayer = RITLBorderLayer.new;
    }

    return objc_getAssociatedObject(self, _cmd);
}


- (RITLBorderLayer *)rightLayer
{
    id layer = objc_getAssociatedObject(self, _cmd);

    if (layer == nil) {

        self.rightLayer = RITLBorderLayer.new;
    }

    return objc_getAssociatedObject(self, _cmd);
}


- (RITLBorderLayer *)bottomLayer
{
    id layer = objc_getAssociatedObject(self, _cmd);

    if (layer == nil) {

        self.bottomLayer = RITLBorderLayer.new;
    }

    return objc_getAssociatedObject(self, _cmd);
}

@end