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

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

UIView扩展

UIView+GLLayout.h


#import 

/// 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方式进行自动布局)