美文网首页
笔记:NSLayoutAnchor方式进行自动布局

笔记:NSLayoutAnchor方式进行自动布局

作者: 林鹏_dev | 来源:发表于2022-04-09 21:42 被阅读0次

    大多数情况下,我们都是使用Masonry这个三方库来进行约束布局,其实苹果开放的NSLayoutAnchor来布局也很方便,他跟Masonry一样底层都是通过NSLayoutConstraint来实现的,因此备份一个UIView的布局扩展代码笔记。

    UIView扩展

    UIView+GLLayout.h

    
    #import <UIKit/UIKit.h>
    
    /// layout布局
    typedef enum : NSUInteger {
        GLLayoutTypeLeft = 0,
        GLLayoutTypeRight,
        GLLayoutTypeTop,
        GLLayoutTypeBottom,
        GLLayoutTypeCenterX,
        GLLayoutTypeCenterY,
        GLLayoutTypeRealLeft,
        GLLayoutTypeRealRight,
        GLLayoutTypeWidth,
        GLLayoutTypeHeight,
    } GLLayoutType;
    
    @interface UIView (GLLayout)
    
    // MARK: - 宽
    /// 宽度
    - (void)gl_width:(CGFloat)width;
    
    /// 宽度=view
    - (void)gl_widthByView:(UIView *)view;
    
    /// 宽度=view+offset
    - (void)gl_widthByView:(UIView *)view offset:(CGFloat)offset;
    
    /// 宽度=view*multiplier
    - (void)gl_widthByView:(UIView *)view multiplier:(CGFloat)multiplier;
    
    ///宽度=view.direction + offset
    - (void)gl_widthByView:(UIView *)view offset:(CGFloat)offset viewDirection:(GLLayoutType)direction ;
    
    // MARK: - 高
    /// 高度
    - (void)gl_height:(CGFloat)height;
    
    /// 高度=view
    - (void)gl_heightByView:(UIView *)view;
    
    /// 高度=view+offset
    - (void)gl_heightByView:(UIView *)view offset:(CGFloat)offset;
    
    /// 高度=view*multiplier
    - (void)gl_heightByView:(UIView *)view multiplier:(CGFloat)multiplier;
    ///高度=view.direction + offset
    - (void)gl_heightByView:(UIView *)view offset:(CGFloat)offset viewDirection:(GLLayoutType)direction ;
    // MARK: - left
    /// left: 相对父视图
    - (void)gl_left:(CGFloat)left;
    
    /// left: 偏移量      view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_left:(CGFloat)left byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    /// real_left: 相对父视图  非RTL自动布局
    - (void)gl_real_left:(CGFloat)real_left;
    
    /// real_left: 偏移量      view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_real_left:(CGFloat)real_left byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    
    // MARK: - right
    /// right: 相对父视图
    - (void)gl_right:(CGFloat)right;
    
    /// right: 偏移量       view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_right:(CGFloat)right byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    /// real_right: 相对父视图
    - (void)gl_real_right:(CGFloat)real_right;
    
    /// real_right: 偏移量       view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_real_right:(CGFloat)real_right byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    
    // MARK: - top
    /// top: 相对父视图
    - (void)gl_top:(CGFloat)top;
    
    /// top: 偏移量       view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_top:(CGFloat)top byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    
    // MARK: - bottom
    /// bottom: 相对父视图
    - (void)gl_bottom:(CGFloat)bottom;
    
    /// bottom: 偏移量       view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_bottom:(CGFloat)bottom byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    
    // MARK: - centerX
    /// centerX: 相对父视图 0是默认父视图居中
    - (void)gl_centerX:(CGFloat)centerX;
    
    /// centerX: 偏移量       view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_centerX:(CGFloat)centerX byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    
    // MARK: - centerY
    /// centerY: 相对父视图 0是默认父视图居中
    - (void)gl_centerY:(CGFloat)centerY;
    
    /// centerY: 偏移量       view: 相对view    direction: 相对view的left / right / top / bottom...
    - (void)gl_centerY:(CGFloat)centerY byView:(UIView *)view viewDirection:(GLLayoutType)direction;
    
    
    @end
    
    
    
    #import "UIView+GLLayout.h"
    
    @implementation UIView (GLLayout)
    
    - (void)removeConstraintWithType:(NSLayoutAttribute)type {
        //找出当前视图对象的指定类型的约束对象
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute == %ld && firstItem == %@",type,self];
        //约束对象列表(width,height)
        NSArray *constantConstraints = [self.constraints filteredArrayUsingPredicate:predicate];
        if (constantConstraints.count > 0) {
            [self removeConstraints:constantConstraints];
        }
        //约束对象列表(left,right,too,bottom,centerX....)
        NSArray *anchorConstraints = [self.superview.constraints filteredArrayUsingPredicate:predicate];
        if (anchorConstraints) {
            [self.superview removeConstraints:anchorConstraints];
        }
    }
    
    // MARK: - 宽
    - (void)gl_width:(CGFloat)width {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeWidth];
        [self.widthAnchor constraintEqualToConstant:width].active = YES;
    }
    
    - (void)gl_widthByView:(UIView *)view {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeWidth];
            [self.widthAnchor constraintEqualToAnchor:view.widthAnchor].active = YES;
        }
    }
    
    - (void)gl_widthByView:(UIView *)view offset:(CGFloat)offset {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeWidth];
            [self.widthAnchor constraintEqualToAnchor:view.widthAnchor constant:offset].active = YES;
        }
    }
    
    - (void)gl_widthByView:(UIView *)view offset:(CGFloat)offset viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeWidth];
            [self.widthAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction]  constant:offset].active = YES;
        }
    }
    
    
    - (void)gl_widthByView:(UIView *)view multiplier:(CGFloat)multiplier {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeWidth];
            [self.widthAnchor constraintEqualToAnchor:view.widthAnchor multiplier:multiplier].active = YES;
        }
    }
    
    // MARK: - 高
    - (void)gl_height:(CGFloat)height {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeHeight];
        [self.heightAnchor constraintEqualToConstant:height].active = YES;
    }
    
    - (void)gl_heightByView:(UIView *)view {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeHeight];
            [self.heightAnchor constraintEqualToAnchor:view.heightAnchor].active = YES;
        }
    }
    
    - (void)gl_heightByView:(UIView *)view offset:(CGFloat)offset {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeHeight];
            [self.heightAnchor constraintEqualToAnchor:view.heightAnchor constant:offset].active = YES;
        }
    }
    
    - (void)gl_heightByView:(UIView *)view offset:(CGFloat)offset viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeHeight];
            [self.heightAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction]  constant:offset].active = YES;
        }
    }
    
    
    - (void)gl_heightByView:(UIView *)view multiplier:(CGFloat)multiplier {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        if (view) {
            [self removeConstraintWithType:NSLayoutAttributeHeight];
            [self.heightAnchor constraintEqualToAnchor:view.heightAnchor multiplier:multiplier].active = YES;
        }
    }
    
    
    // MARK: - left
    - (void)gl_left:(CGFloat)left {
        [self gl_left:left byView:nil viewDirection:GLLayoutTypeLeft];
    }
    
    - (void)gl_left:(CGFloat)left byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeLeading];
        if (view) {
            [self.leadingAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:left].active = YES;
        }else {
            [self.leadingAnchor constraintEqualToAnchor:self.superview.leadingAnchor constant:left].active = YES;
        }
    }
    
    - (void)gl_real_left:(CGFloat)real_left {
        [self gl_real_left:real_left byView:nil viewDirection:GLLayoutTypeRealLeft];
    }
    
    - (void)gl_real_left:(CGFloat)real_left byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeLeft];
        if (view) {
            [self.leftAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:real_left].active = YES;
        }else {
            [self.leftAnchor constraintEqualToAnchor:self.superview.leftAnchor constant:real_left].active = YES;
        }
    }
    
    // MARK: - right
    - (void)gl_right:(CGFloat)right {
        [self gl_right:right byView:nil viewDirection:GLLayoutTypeRight];
    }
    
    - (void)gl_right:(CGFloat)right byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeTrailing];
        if (view) {
            [self.trailingAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:-right].active = YES;
        }else {
            [self.trailingAnchor constraintEqualToAnchor:self.superview.trailingAnchor constant:-right].active = YES;
        }
    }
    
    - (void)gl_real_right:(CGFloat)real_right {
        [self gl_real_right:real_right byView:nil viewDirection:GLLayoutTypeRealRight];
    }
    
    - (void)gl_real_right:(CGFloat)real_right byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeRight];
        if (view) {
            [self.rightAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:-real_right].active = YES;
        }else {
            [self.rightAnchor constraintEqualToAnchor:self.superview.rightAnchor constant:-real_right].active = YES;
        }
    }
    
    // MARK: - top
    - (void)gl_top:(CGFloat)top {
        [self gl_top:top byView:nil viewDirection:GLLayoutTypeTop];
    }
    
    - (void)gl_top:(CGFloat)top byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeTop];
        if (view) {
            [self.topAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:top].active = YES;
        }else {
            [self.topAnchor constraintEqualToAnchor:self.superview.topAnchor constant:top].active = YES;
        }
    }
    
    // MARK: - bottom
    - (void)gl_bottom:(CGFloat)bottom {
        [self gl_bottom:bottom byView:nil viewDirection:GLLayoutTypeBottom];
    }
    
    - (void)gl_bottom:(CGFloat)bottom byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeBottom];
        if (view) {
            [self.bottomAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:-bottom].active = YES;
        }else {
            [self.bottomAnchor constraintEqualToAnchor:self.superview.bottomAnchor constant:-bottom].active = YES;
        }
    }
    
    // MARK: - centerX
    - (void)gl_centerX:(CGFloat)centerX {
        [self gl_centerX:centerX byView:nil viewDirection:GLLayoutTypeCenterX];
    }
    
    - (void)gl_centerX:(CGFloat)centerX byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeCenterX];
        if (view) {
            [self.centerXAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:centerX].active = YES;
        }else {
            [self.centerXAnchor constraintEqualToAnchor:self.superview.centerXAnchor constant:centerX].active = YES;
        }
    }
    
    // MARK: - centerY
    - (void)gl_centerY:(CGFloat)centerY {
        [self gl_centerY:centerY byView:nil viewDirection:GLLayoutTypeCenterY];
    }
    
    - (void)gl_centerY:(CGFloat)centerY byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        [self removeConstraintWithType:NSLayoutAttributeCenterY];
        if (view) {
            [self.centerYAnchor constraintEqualToAnchor:[self byView:view viewDirection:direction] constant:centerY].active = YES;
        }else {
            [self.centerYAnchor constraintEqualToAnchor:self.superview.centerYAnchor constant:centerY].active = YES;
        }
    }
    
    - (NSLayoutAnchor *)byView:(UIView *)view viewDirection:(GLLayoutType)direction {
        NSLayoutAnchor *anchor = nil;
        switch (direction) {
            case GLLayoutTypeTop:
                anchor = view.topAnchor;
                break;
            case GLLayoutTypeLeft:
                anchor = view.leadingAnchor;
                break;
            case GLLayoutTypeBottom:
                anchor = view.bottomAnchor;
                break;
            case GLLayoutTypeRight:
                anchor = view.trailingAnchor;
                break;
            case GLLayoutTypeCenterX:
                anchor = view.centerXAnchor;
                break;
            case GLLayoutTypeCenterY:
                anchor = view.centerYAnchor;
                break;
            case GLLayoutTypeRealLeft:
                anchor = view.leftAnchor;
                break;
            case GLLayoutTypeRealRight:
                anchor = view.rightAnchor;
                break;
            case GLLayoutTypeHeight:
                anchor = view.heightAnchor;
                break;
            case GLLayoutTypeWidth:
                anchor = view.widthAnchor;
                break;
            default:
                break;
        }
        return anchor;
    }
    
    @end
    
    

    使用

        UIView *w = [UIView new];
        w.backgroundColor = [UIColor redColor];
        [self.view addSubview:w];
        
        //设置(设置和更新都是一个接口不会有代码约束冲突)
        [w gl_top:100]; //更新top:[w gl_top:120];
        [w gl_left:100];
        [w gl_width:100];
        [w gl_height:100];
    

    相关文章

      网友评论

          本文标题:笔记:NSLayoutAnchor方式进行自动布局

          本文链接:https://www.haomeiwen.com/subject/wphmsrtx.html