筆記:NSLayoutAnchor方式進(jìn)行自動(dòng)布局

大多數(shù)情況下,我們都是使用Masonry這個(gè)三方庫(kù)來(lái)進(jìn)行約束布局窿凤,其實(shí)蘋(píng)果開(kāi)放的NSLayoutAnchor來(lái)布局也很方便仅偎,他跟Masonry一樣底層都是通過(guò)NSLayoutConstraint來(lái)實(shí)現(xiàn)的,因此備份一個(gè)UIView的布局?jǐn)U展代碼筆記雳殊。

UIView擴(kuò)展

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: 相對(duì)父視圖
- (void)gl_left:(CGFloat)left;

/// left: 偏移量      view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_left:(CGFloat)left byView:(UIView *)view viewDirection:(GLLayoutType)direction;

/// real_left: 相對(duì)父視圖  非RTL自動(dòng)布局
- (void)gl_real_left:(CGFloat)real_left;

/// real_left: 偏移量      view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_real_left:(CGFloat)real_left byView:(UIView *)view viewDirection:(GLLayoutType)direction;


// MARK: - right
/// right: 相對(duì)父視圖
- (void)gl_right:(CGFloat)right;

/// right: 偏移量       view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_right:(CGFloat)right byView:(UIView *)view viewDirection:(GLLayoutType)direction;

/// real_right: 相對(duì)父視圖
- (void)gl_real_right:(CGFloat)real_right;

/// real_right: 偏移量       view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_real_right:(CGFloat)real_right byView:(UIView *)view viewDirection:(GLLayoutType)direction;


// MARK: - top
/// top: 相對(duì)父視圖
- (void)gl_top:(CGFloat)top;

/// top: 偏移量       view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_top:(CGFloat)top byView:(UIView *)view viewDirection:(GLLayoutType)direction;


// MARK: - bottom
/// bottom: 相對(duì)父視圖
- (void)gl_bottom:(CGFloat)bottom;

/// bottom: 偏移量       view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_bottom:(CGFloat)bottom byView:(UIView *)view viewDirection:(GLLayoutType)direction;


// MARK: - centerX
/// centerX: 相對(duì)父視圖 0是默認(rèn)父視圖居中
- (void)gl_centerX:(CGFloat)centerX;

/// centerX: 偏移量       view: 相對(duì)view    direction: 相對(duì)view的left / right / top / bottom...
- (void)gl_centerX:(CGFloat)centerX byView:(UIView *)view viewDirection:(GLLayoutType)direction;


// MARK: - centerY
/// centerY: 相對(duì)父視圖 0是默認(rèn)父視圖居中
- (void)gl_centerY:(CGFloat)centerY;

/// centerY: 偏移量       view: 相對(duì)view    direction: 相對(duì)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 {
    //找出當(dāng)前視圖對(duì)象的指定類(lèi)型的約束對(duì)象
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute == %ld && firstItem == %@",type,self];
    //約束對(duì)象列表(width橘沥,height)
    NSArray *constantConstraints = [self.constraints filteredArrayUsingPredicate:predicate];
    if (constantConstraints.count > 0) {
        [self removeConstraints:constantConstraints];
    }
    //約束對(duì)象列表(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];
    
    //設(shè)置(設(shè)置和更新都是一個(gè)接口不會(huì)有代碼約束沖突)
    [w gl_top:100]; //更新top:[w gl_top:120];
    [w gl_left:100];
    [w gl_width:100];
    [w gl_height:100];
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夯秃,一起剝皮案震驚了整個(gè)濱河市座咆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌仓洼,老刑警劉巖介陶,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異色建,居然都是意外死亡哺呜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)箕戳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)某残,“玉大人国撵,你說(shuō)我怎么就攤上這事〔J” “怎么了介牙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)澳厢。 經(jīng)常有香客問(wèn)我环础,道長(zhǎng),這世上最難降的妖魔是什么赏酥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任喳整,我火速辦了婚禮谆构,結(jié)果婚禮上裸扶,老公的妹妹穿的比我還像新娘。我一直安慰自己搬素,他們只是感情好呵晨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著熬尺,像睡著了一般摸屠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粱哼,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天季二,我揣著相機(jī)與錄音,去河邊找鬼揭措。 笑死胯舷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绊含。 我是一名探鬼主播桑嘶,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼躬充!你這毒婦竟也來(lái)了逃顶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤充甚,失蹤者是張志新(化名)和其女友劉穎以政,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伴找,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盈蛮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疆瑰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眉反。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昙啄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寸五,到底是詐尸還是另有隱情梳凛,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布梳杏,位于F島的核電站韧拒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏十性。R本人自食惡果不足惜叛溢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望劲适。 院中可真熱鬧楷掉,春花似錦、人聲如沸霞势。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愕贡。三九已至草雕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間固以,已是汗流浹背墩虹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留憨琳,地道東北人诫钓。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像栽渴,于是被迫代替她去往敵國(guó)和親尖坤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容