大多数情况下,我们都是使用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];
网友评论