1.實現自動佈局的幾種途徑:1.原生api,VFL、storyboard、第三方masonryapi
2.原生api數組
/** 系統默認添加約束的方法,它是NSLayoutConstraint的類方法 @param view1 想要添加約束的控件 @param attr1 想要添加約束的方向 @param relation 傳入與約束值的關係,大於、等於仍是小於 @param view2 被參照對象 @param attr2 被參照對象所被參照的方向,如頂部、左邊、右邊等 @param multiplier 間距倍數關係 @param c 最終的差值 @return NSLayoutConstraint對象 */ //+(instancetype)constraintWithItem:(id)view1 // attribute:(NSLayoutAttribute)attr1 // relatedBy:(NSLayoutRelation)relation // toItem:(nullable id)view2 // attribute:(NSLayoutAttribute)attr2 // multiplier:(CGFloat)multiplier // constant:(CGFloat)c //#pragma clang diagnostic push //#pragma clang diagnostic ignored "-Warc-" //#pragma clang diagnostic pop -(void)sysAutolayout{ /////////////////////////////////////////// red view //////////////////////////////////////////////// UIView *redView = [[UIView alloc] init]; [self.view addSubview:redView]; redView.backgroundColor = [UIColor redColor]; //⚠️:必定要加上這句代碼,不然添加的約束會有衝突 redView.translatesAutoresizingMaskIntoConstraints = NO; //左邊的約束 NSLayoutConstraint *redLeftCons = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:20]; // [self.view addConstraint:redLeftCons]; redLeftCons.active = YES;//這是官方建議的方法 //底部的約束 NSLayoutConstraint *redBottomCons = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:-20]; //⚠️:只在沒有參照控件時(即toItem爲nil),約束才添加到本身身上,否則添加到父視圖上 // [self.view addConstraint:redBottomCons]; redBottomCons.active = YES; //寬度約束 //能夠參照其餘控件設置約束,以下: // [NSLayoutConstraint constraintWithItem:redView // attribute:NSLayoutAttributeWidth // relatedBy:NSLayoutRelationEqual // toItem:self.view // attribute:NSLayoutAttributeWidth // multiplier:0.5 // constant:0]; //也能夠不參照其餘控件 NSLayoutConstraint *redWidthCons = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:50]; //這裏沒有參照控件,因此約束添加到本身身上 // [redView addConstraint:redWidthCons]; redWidthCons.active = YES; //長度約束,同寬度約束 NSLayoutConstraint *redHeightCons = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:40]; // [redView addConstraint:redHeightCons]; redHeightCons.active = YES; //////////////////////////////// blue view/////////////////////////////// UIView *blueView = [[UIView alloc] init]; [self.view addSubview:blueView]; blueView.backgroundColor = [UIColor blueColor]; _blueView = blueView; blueView.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *blueLeftCons = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeRight multiplier:1 constant:10]; [self.view addConstraint:blueLeftCons]; NSLayoutConstraint *blueBottomCons = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; [self.view addConstraint:blueBottomCons]; NSLayoutConstraint *blueWidthCons = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1 constant:50]; [blueView addConstraint:blueWidthCons]; NSLayoutConstraint *blueHeightCons = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1 constant:50]; [blueView addConstraint:blueHeightCons]; ///////////////////////////// yellow view ///////////////////////////////////// UIView *yellowView = [[UIView alloc] init]; [self.view addSubview:yellowView]; yellowView.backgroundColor = [UIColor yellowColor]; yellowView.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *yellowLeftCons = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeRight multiplier:1 constant:10]; [self.view addConstraint:yellowLeftCons]; NSLayoutConstraint *yellowBottomCons = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; [self.view addConstraint:yellowBottomCons]; NSLayoutConstraint *yellowWidthCons = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1 constant:50]; [yellowView addConstraint:yellowWidthCons]; NSLayoutConstraint *yellowHeightCons = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1 constant:50]; [yellowView addConstraint:yellowHeightCons]; //低優先級的約束 NSLayoutConstraint *yellowLeftCons_1 = [NSLayoutConstraint constraintWithItem:yellowView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeRight multiplier:1 constant:10]; //優先級的範圍時0-1000,默認是1000 //數字越大,優先級越高 //優先級相同時,會形成約束衝突 yellowLeftCons_1.priority = 250;//此時優先級低於yellowLeftCons,不執行 [self.view addConstraint:yellowLeftCons_1]; [self.view removeConstraint:yellowLeftCons_1]; }
2.vflide
/** VFL建立約束的API @param format 傳入某種格式構成的字符串,用以表達須要添加的約束,如@"H:|-margin-[redView(50)]"表示:水平方向上,redview與父控件左邊緣保持"margin"間距,redview的寬度爲50 @param opts 對齊方式,相對於format中全部視圖的對齊約束,若是format只有一個view時,能夠不設置 @param metrics 通常傳入以間距爲key的字典,如:@{@"margin":@20},key要與format參數裏所填寫的"margin"相同 @param views 傳入約束中提到的view,也是字典,如:@{@"redView":redView},key要與format參數裏所填寫的"redView"相同 @return 返回約束的數組 */ //+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views{} //vfl是基於NSLayoutConstraint的一種自動佈局方式 //format 語法: //1.每句的前面都要加@"H:"或者@"V:",分別表明着水平和垂直方向 //2.@"|"表明着邊界 //3.@"-"用來表示間隙,通常以這樣的形式出現@"-20-",也能夠先填寫標示@"-margin-",以後經過metrics賦值 //4.@"[]"用來存放須要添加約束的view,想要直接設置寬高就這樣[redView(50)] //示例 //H:[cancelButton(72)]-12-[acceptButton(50)] //cancelButton寬72,acceptButton寬50,它們之間間距12 // //H:[wideView(>=60@700)] //wideView寬度大於等於60point,該約束條件優先級爲700(優先級最大值爲1000,優先級越高的約束條件越先被知足) // //V:[redBox][yellowBox(==redBox)] //垂直方向上,先有一個redBox,其下方緊接一個高度等於redBox高度的yellowBox // //H:|-10-[Find]-[FindNext]-[FindField(>=20)]-| //水平方向上,Find距離父view左邊緣間隔10,以後是FindNext距離Find間隔默認寬度;再以後是寬度不小於20的FindField,它和FindNext以及父view右邊邊緣的間距都是默認寬度。(豎線「|」表示superview的邊緣)。 -(void)vflAutolayout{ UIView *redView = [[UIView alloc] init]; [self.view addSubview:redView]; redView.backgroundColor = [UIColor redColor]; redView.translatesAutoresizingMaskIntoConstraints = NO; //這個方法會自動把傳入的參數以字典的形式返回,字典的key就是其自己的名字 NSDictionary *redViewInfo = NSDictionaryOfVariableBindings(redView); NSString *hFormat = @"H:|-margin-[redView(redWidth)]"; NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hFormat options:kNilOptions metrics:@{@"margin":@20,@"redWidth":@50} views:redViewInfo]; // [self.view addConstraints:hCons]; [NSLayoutConstraint activateConstraints:hCons]; NSString *vFormat = @"V:|-margin-[redView(redHeight)]"; NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vFormat options:kNilOptions metrics:@{@"margin":@20,@"redHeight":@100} views:redViewInfo]; // [self.view addConstraints:vCons]; [NSLayoutConstraint activateConstraints:vCons]; } -(void)vflAutolayout_complex{ UIView *redView = [[UIView alloc] init]; [self.view addSubview:redView]; redView.backgroundColor = [UIColor redColor]; redView.translatesAutoresizingMaskIntoConstraints = NO; UIView *blueView = [[UIView alloc] init]; [self.view addSubview:blueView]; blueView.backgroundColor = [UIColor blueColor]; _blueView = blueView; blueView.translatesAutoresizingMaskIntoConstraints = NO; UIView *yellowView = [[UIView alloc] init]; [self.view addSubview:yellowView]; yellowView.backgroundColor = [UIColor yellowColor]; yellowView.translatesAutoresizingMaskIntoConstraints = NO; ////////////////////////////////////////////////////////////// //這個方法會自動把傳入的參數以字典的形式返回,字典的key就是其自己的名字 NSDictionary *viewInfo = NSDictionaryOfVariableBindings(redView,blueView,yellowView); NSDictionary *metrics = @{@"margin":@20}; NSString *hConsFormat = @"H:|-margin-[redView(50)]-margin-[blueView(==redView)]-margin-[yellowView(==redView)]"; NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hConsFormat options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:metrics views:viewInfo]; [NSLayoutConstraint activateConstraints:hCons]; //設置約束的優先級,須要明確是哪一個約束須要設置優先級 NSString *hConsFormat_1 = @"H:|-margin-[redView(50)]-margin@250-[yellowView(==redView)]"; NSArray *hCons_1 = [NSLayoutConstraint constraintsWithVisualFormat:hConsFormat_1 options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:metrics views:viewInfo]; [NSLayoutConstraint activateConstraints:hCons_1]; NSString *vConsFormat = @"V:|-margin-[redView(50)]"; NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vConsFormat options:kNilOptions metrics:metrics views:viewInfo]; [NSLayoutConstraint activateConstraints:vCons]; }
3.masonry佈局
-(void)masonry_autolayout{ UIView *redView = [[UIView alloc] init]; [self.view addSubview:redView]; redView.backgroundColor = [UIColor redColor]; _redView = redView; UIView *blueView = [[UIView alloc] init]; [self.view addSubview:blueView]; blueView.backgroundColor = [UIColor blueColor]; _blueView = blueView; UIView *yellowView = [[UIView alloc] init]; [self.view addSubview:yellowView]; yellowView.backgroundColor = [UIColor yellowColor]; _yellowView = yellowView; [redView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.leading.equalTo(self.view).offset(20); make.width.height.equalTo(@50); }]; [blueView mas_makeConstraints:^(MASConstraintMaker *make) { make.leading.mas_equalTo(redView.mas_trailing).offset(10); make.top.width.height.equalTo(redView); }]; // [yellowView mas_makeConstraints:^(MASConstraintMaker *make) { // make.top.width.height.equalTo(redView); // make.leading.mas_equalTo(blueView.mas_trailing).offset(10); // make.leading.mas_equalTo(redView.mas_trailing).offset(10).priorityLow(); // }]; [yellowView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.width.height.equalTo(redView); self.leftCons = make.leading.mas_equalTo(blueView.mas_trailing).offset(10); }]; } -(void)update_masonry_layout{ _blueView.hidden = YES; // [_yellowView mas_remakeConstraints:^(MASConstraintMaker *make) { // make.top.width.height.equalTo(self.redView); // make.leading.mas_equalTo(self.redView.mas_trailing).offset(10); // }]; //mas_updateConstraints 所作的只是在原有約束的基礎上添加約束,若是原來的約束中存在對應的約束就覆蓋原約束 //若是原來的約束不存在對應的約束,而且有約束與新的約束相沖突,就須要先刪除原約束 [self.leftCons uninstall]; [_yellowView mas_updateConstraints:^(MASConstraintMaker *make) { make.leading.mas_equalTo(self.redView.mas_trailing).offset(10); }]; }
4.更新約束的代碼示例code
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //blueview 被移除後,yellowLeftCons就不成立了,yellowLeftCons_1生效 // [_blueView removeFromSuperview]; [self update_masonry_layout]; [UIView animateWithDuration:1 animations:^{ [self.view layoutIfNeeded]; }]; [self update_masonry_layout]; }