设定上下左右内边距
- 约束是相对于参照试图坐标系。也可以单独写针对参照试图的约束方向
- equalTo()针对的的是对象,例如试图对象,试图的约束对象
- edges内边距,针对参照试图的内边距,四个方向大于0代表相对于参照试图内部展示。
- offset(基本数据类型),如果是水平方向,设置的值大于0,是相对于参照试图的右边布局,否则是左方布局。
如果是竖直方向,设置的值大于0,是相对于参考试图的下方布局,否则是上方布局。 - mas_equalTo(),可以写基本数值类型,也可以使用参照对象等。
- (void)viewDidLoad {
[super viewDidLoad];
UIView *contentView = [UIView new];
contentView.backgroundColor = [UIColor redColor];
[self.view addSubview:contentView];
if (arc4random() % 2) {
// 直接设置edges
[contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsMake(10 + 64.f, 10, 10, 10));
}];
} else {
// // 设置 left, right, bottom, top
UIView *supperView = self.view;
[contentView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.top.equalTo(supperView.mas_top).offset(10 + 64);
// make.left.equalTo(supperView.mas_left).offset(10);
// make.bottom.equalTo(supperView.mas_bottom).offset(-10);
// make.right.equalTo(supperView.mas_right).offset(-10);
make.top.equalTo(supperView).offset(10 + 64);
make.left.equalTo(supperView).offset(10);
make.bottom.equalTo(supperView).offset(-10);
make.right.equalTo(supperView).offset(-10);
}];
}
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 22.47.34.png
设定具体尺寸
- (void)viewDidLoad {
[super viewDidLoad];
UIView *redView = [UIView new];
redView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5f];
[self.view addSubview:redView];
UIView *yellowView = [UIView new];
yellowView.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.5f];
[self.view addSubview:yellowView];
UIView *supperView = self.view;
// 设定尺寸100x100,距离左边10,下边-10
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(100, 100));
make.left.equalTo(supperView.mas_left).offset(10);
make.bottom.equalTo(supperView.mas_bottom).offset(-10);
}];
// 设定尺寸100x100,居中
[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(100, 100));
make.center.equalTo(supperView);
}];
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.04.29.png
根据相对性设置宽高
- (void)viewDidLoad {
[super viewDidLoad];
UIView *redView = [UIView new];
redView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5f];
[self.view addSubview:redView];
UIView *yellowView = [UIView new];
yellowView.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.5f];
[self.view addSubview:yellowView];
UIView *supperView = self.view;
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
// 距离左边10
make.left.equalTo(supperView.mas_left).offset(10);
// 距离底部-10
make.bottom.equalTo(supperView.mas_bottom).offset(-10);
// 高度为 supperView 高度一半
make.height.equalTo(supperView.mas_height).multipliedBy(0.5);
// 宽度为 yellowView 的 1/4
make.width.equalTo(yellowView.mas_width).multipliedBy(0.25);
}];
[yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
// 距离右边-10
make.right.equalTo(supperView.mas_right).offset(-10);
// 距离底部-10
make.bottom.equalTo(supperView.mas_bottom).offset(-10);
// 高度为 redView 1/2
make.height.equalTo(redView.mas_height).multipliedBy(0.5);
// 距离 redView 右边距离为10
make.left.equalTo(redView.mas_right).offset(10.f);
}];
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.08.10.png
根据子view宽高确定父view宽高
- (void)viewDidLoad {
[super viewDidLoad];
// 载体view
UIView *contentView = [[UIView alloc] init];
contentView.layer.borderColor = [UIColor redColor].CGColor;
contentView.layer.borderWidth = 0.5f;
[self.view addSubview:contentView];
// 红色view
UIView *redView = [UIView new];
redView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.75f];
[contentView addSubview:redView];
// 绿色view
UIView *greenView = [UIView new];
greenView.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.75f];
[contentView addSubview:greenView];
if (arc4random() % 2) {
/* ---------------------- */
/* lessThanOrEqualTo的使用 */
/* ---------------------- */
[contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
}];
UIView *supperView = contentView;
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设定尺寸
make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
// 左边与 supperView 左边对齐
make.left.equalTo(supperView.mas_left);
// 顶部与 supperView 顶部对齐
make.top.equalTo(supperView.mas_top);
// 底部小于或者等于 supperView 的底部
make.bottom.lessThanOrEqualTo(supperView.mas_bottom);
}];
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设定尺寸
make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
// 左边距离 redView 右边距离10
make.left.equalTo(redView.mas_right).offset(10);
// 顶部与 supperView 顶部对齐
make.top.equalTo(supperView.mas_top);
// 右边与 supperView 右边对齐
make.right.equalTo(supperView.mas_right);
// 底部小于或者等于 supperView 的底部
make.bottom.lessThanOrEqualTo(supperView.mas_bottom);
}];
} else {
/* ------------------------- */
/* greaterThanOrEqualTo的使用 */
/* ------------------------- */
[contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
// 底部大于或者等于 redView 的底部
make.bottom.greaterThanOrEqualTo(redView.mas_bottom);
// 底部大于或者等于 greenView 的底部
make.bottom.greaterThanOrEqualTo(greenView.mas_bottom);
}];
UIView *supperView = contentView;
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设定尺寸
make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
// 左边与 supperView 左边对齐
make.left.equalTo(supperView.mas_left);
// 顶部与 supperView 顶部对齐
make.top.equalTo(supperView.mas_top);
}];
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设定尺寸
make.size.mas_equalTo(CGSizeMake(arc4random() % 50 + 50, arc4random() % 50 + 50));
// 左边距离 redView 右边距离10
make.left.equalTo(redView.mas_right).offset(10);
// 顶部与 supperView 顶部对齐
make.top.equalTo(supperView.mas_top);
// 右边与 supperView 右边对齐
make.right.equalTo(supperView.mas_right);
}];
}
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.11.21.png
修改约束的情形
- (void)viewDidLoad {
[super viewDidLoad];
UIView *redView = [UIView new];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
UIView *supperView = self.view;
if (arc4random() % 2) {
/* --------------------------- */
/* mas_updateConstraints更新约束 */
/* --------------------------- */
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
// 距离左边10
make.left.equalTo(supperView.mas_left).offset(10.f);
// 距离底部-10
make.bottom.equalTo(supperView.mas_bottom).offset(-10.f);
// 设定尺寸100x100
make.size.mas_equalTo(CGSizeMake(100, 100));
}];
[GCDQueue executeInMainQueue:^{
// 更新约束
[redView mas_updateConstraints:^(MASConstraintMaker *make) {
// 重新设定尺寸为200x200
make.size.mas_equalTo(CGSizeMake(200, 200));
}];
} afterDelaySecs:2.f];
} else {
/* ---------------------- */
/* MASConstraint对象更新约束 */
/* ---------------------- */
MASConstraint __block *constraint = nil;
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
// 距离左边10
make.left.equalTo(supperView.mas_left).offset(10.f);
// 距离底部-10
make.bottom.equalTo(supperView.mas_bottom).offset(-10.f);
// (获取设定尺寸的约束) 设定尺寸100x100
constraint = make.size.mas_equalTo(CGSizeMake(100, 100));
}];
[GCDQueue executeInMainQueue:^{
// 重新设定尺寸为200x200
constraint.mas_equalTo(CGSizeMake(200, 200));
} afterDelaySecs:2.f];
}
}
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.25.19.png
Simulator Screen Shot - iPod touch (7th generation) - 2021-02-27 at 23.25.42.png
cell自动算高度-版本1
- (void)viewDidLoad {
[super viewDidLoad];
// 通知中心(检测屏幕旋转)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationEvent:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
//
// 数据源
self.datas = [NSMutableArray array];
[self.datas addObject:@"篱笆墙是个历史的产物,它的产生和消失,是农村发展、农民生活变化的见证。"];
[self.datas addObject:@"漆太太,是陕西陇县人,到底姓什么,也真没有知根知底的。"];
[self.datas addObject:@"那一年,漆太太的丈夫随渔船下海,突然遇到狂风暴雨,连人带船沉没了大海,从此没有消息。"];
[self.datas addObject:@"那时虽说是大集体,可是对五保户,那是照顾有加。凡是生产队分东西,如粮食、柴草,蔬菜等,都是要挑最好的先给漆太太送到家。"];
[self.datas addObject:@"围绕村子里这道最后的篱笆墙,生发了许多故事,至今还流传在故乡的巷子里,铭刻在村里人的记忆中。"];
// tableView
self.tableView = [[UITableView alloc] init];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
// 注册cell
[self.tableView registerClass:[CellAutoHeightInfoCell class] forCellReuseIdentifier:@"CellAutoHeightInfoCell"];
// 添加tableView约束
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsMake(0, 0, 0, 0));
}];
// 设定预估行高
self.tableView.estimatedRowHeight = 45.f;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.datas.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CellAutoHeightInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellAutoHeightInfoCell" forIndexPath:indexPath];
cell.data = self.datas[indexPath.row];
[cell loadContent];
return cell;
}
#pragma mark - notificationEvent
- (void)notificationEvent:(NSNotification *)notification {
if ([notification.name isEqualToString:UIApplicationDidChangeStatusBarOrientationNotification]) {
// 屏幕刷新后重新加载cell
[self.tableView reloadData];
}
}
CustomCellAutoHeightInfoCell
@interface CustomCellAutoHeightInfoCell ()
@property (nonatomic, strong) UIImageView *iconImageView;
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIView *lineView;
@end
@implementation CustomCellAutoHeightInfoCell
- (void)buildSubview {
self.iconImageView = [UIImageView new];
self.iconImageView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5f];
[self.contentView addSubview:self.iconImageView];
self.label = [UILabel new];
self.label.numberOfLines = 4;
[self.contentView addSubview:self.label];
self.lineView = [UIView new];
self.lineView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.25f];
[self.contentView addSubview:self.lineView];
UIView *supperView = self.contentView;
[self.iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(supperView.mas_top).offset(10);
make.left.equalTo(supperView.mas_left).offset(10);
make.size.mas_equalTo(CGSizeMake(50.f, 50.f));
make.bottom.lessThanOrEqualTo(supperView.mas_bottom).offset(-10.f);
}];
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(supperView.mas_top).offset(10);
make.left.equalTo(self.iconImageView.mas_right).offset(10.f);
make.right.equalTo(supperView.mas_right).offset(-10.f);
make.bottom.lessThanOrEqualTo(supperView.mas_bottom).offset(-10.f);
}];
[self.lineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(supperView.mas_bottom);
make.left.equalTo(self.contentView.mas_left).offset(10.f);
make.right.equalTo(self.contentView.mas_right).offset(-10.f);
make.height.equalTo(@1);
}];
}
- (void)loadContent {
// 更新约束
[self.lineView mas_updateConstraints:^(MASConstraintMaker *make) {
if (self.indexPath.row % 2) {
make.left.equalTo(self.contentView.mas_left).offset(50.f);
make.right.equalTo(self.contentView.mas_right).offset(-50.f);
} else {
make.left.equalTo(self.contentView.mas_left).offset(10.f);
make.right.equalTo(self.contentView.mas_right).offset(-10.f);
}
}];
// 设定最大行宽
self.label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 10 - 50 - 20;
// 加载数据
self.label.attributedText = [NSAttributedString attributedStringWithString:self.data config:^(NSMutableArray<AttributedStringConfig *> *configs) {
NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
style.lineSpacing = 5.f;
[configs addObject:[ParagraphAttributeConfig configWithParagraphStyle:style]];
[configs addObject:[FontAttributeConfig configWithFont:[UIFont systemFontOfSize:12.f]]];
}];;
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
[super setHighlighted:highlighted animated:animated];
// 更新约束值
[self.iconImageView mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView.mas_left).offset(highlighted ? 15 : 10);
}];
[UIView animateWithDuration:0.25f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[self.contentView layoutIfNeeded];
self.contentView.backgroundColor = highlighted ? [[UIColor grayColor] colorWithAlphaComponent:0.15f] : [UIColor whiteColor];
} completion:nil];
}
image.png
image.png
延展缩放
@interface ExpendLayoutCell ()
@property (nonatomic, strong) UIView *lineView;
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) MASConstraint *constraint;
@end
@implementation ExpendLayoutCell
- (void)buildSubview {
self.lineView = [UIView new];
self.lineView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5f];
[self.contentView addSubview:self.lineView];
[self.lineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.bottom.mas_equalTo(0);
make.right.mas_equalTo(0);
make.height.mas_equalTo(0.5);
}];
self.label = [UILabel new];
self.label.numberOfLines = 0;
[self.contentView addSubview:self.label];
[self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10.f);
make.top.mas_equalTo(10.f);
make.right.mas_equalTo(-10.f);
make.height.mas_equalTo([UIFont labelFontSize]);
}];
}
- (void)loadContent {
self.label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
ExpendLayoutCellModel *model = self.data;
self.label.text = model.string;
if (model.expend == YES) {
[self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10.f);
make.top.mas_equalTo(10.f);
make.right.mas_equalTo(-10.f);
make.bottom.mas_lessThanOrEqualTo(-10.f);
}];
} else {
[self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10.f);
make.top.mas_equalTo(10.f);
make.right.mas_equalTo(-10.f);
make.height.mas_equalTo([UIFont labelFontSize]);
}];
}
}
- (void)selectedEvent {
ExpendLayoutCellModel *model = self.data;
if (model.expend == YES) {
[self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10.f);
make.top.mas_equalTo(10.f);
make.right.mas_equalTo(-10.f);
make.height.mas_equalTo([UIFont labelFontSize]);
}];
} else {
[self.label mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10.f);
make.top.mas_equalTo(10.f);
make.right.mas_equalTo(-10.f);
make.bottom.mas_lessThanOrEqualTo(-10.f);
}];
}
model.expend = !model.expend;
// 执行动画
[UIView animateWithDuration:0.25f animations:^{
[self.label.superview layoutIfNeeded];
}];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
@end
约束优先级
typedef enum : NSUInteger {
kDeleteOrangeViewButton = 1000,
kDeleteYellowViewButton,
} EPriorityConstraintViewControllerTagValue;
@interface PriorityConstraintViewController ()
@property (nonatomic ,strong) UIView *orangeView;
@property (nonatomic ,strong) UIView *yellowView;
@property (nonatomic ,strong) UIView *greenView;
@end
@implementation PriorityConstraintViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initButtons];
self.orangeView = [[UIView alloc] init];
self.orangeView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:self.orangeView];
self.yellowView = [[UIView alloc] init];
self.yellowView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.yellowView];
self.greenView = [[UIView alloc] init];
self.greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.greenView];
// 橘色(作为基准)
[self.orangeView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(50);
make.bottom.offset(-10);
make.left.offset(10);
}];
// 黄色
[self.yellowView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(50);
make.bottom.offset(-10);
// 用优先级来设定满足条件,此处为2种情况
make.left.equalTo(self.orangeView.mas_right).offset(10).priorityHigh();
make.left.equalTo(self.view.mas_left).offset(10).priorityMedium();
}];
// 绿色
[self.greenView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(50);
make.bottom.offset(-10);
// 用优先级来设定满足条件,此处为3种情况
make.left.equalTo(self.yellowView.mas_right).offset(10).priorityHigh();
make.left.equalTo(self.orangeView.mas_right).offset(10).priorityMedium();
make.left.equalTo(self.view.mas_left).offset(10).priorityLow();
}];
}
- (void)initButtons {
UIButton *deleteOrangeYellowViewButton = [UIButton buttonWithType:UIButtonTypeSystem];
deleteOrangeYellowViewButton.tag = kDeleteOrangeViewButton;
[deleteOrangeYellowViewButton setTitle:@"删除橘色view" forState:UIControlStateNormal];
[deleteOrangeYellowViewButton addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:deleteOrangeYellowViewButton];
[deleteOrangeYellowViewButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(64 + 10.f);
make.left.mas_equalTo(10.f);
}];
UIButton *deleteYellowViewButton = [UIButton buttonWithType:UIButtonTypeSystem];
deleteYellowViewButton.tag = kDeleteYellowViewButton;
[deleteYellowViewButton setTitle:@"删除黄色view" forState:UIControlStateNormal];
[deleteYellowViewButton addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:deleteYellowViewButton];
[deleteYellowViewButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(deleteOrangeYellowViewButton.mas_bottom).offset(10.f);
make.left.mas_equalTo(10.f);
}];
}
- (void)buttonsEvent:(UIButton *)button {
if (button.tag == kDeleteOrangeViewButton) {
[self.orangeView removeFromSuperview];
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
} else if (button.tag == kDeleteYellowViewButton) {
[self.yellowView removeFromSuperview];
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
}
@end
image.png
Install的使用
@interface ConstraintInstallViewController () {
BOOL _isUninstalled;
}
@property (nonatomic, strong) MASConstraint *constraint;
@end
@implementation ConstraintInstallViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initButton];
UIView *redView = [UIView new];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.mas_equalTo(100).priorityMedium();
make.center.equalTo(self.view);
self.constraint = make.width.height.mas_equalTo(200).priorityHigh();
}];
}
- (void)initButton {
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"uninstall" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.view.mas_centerX);
make.bottom.mas_equalTo(-10);
}];
}
- (void)buttonsEvent:(UIButton *)button {
if (_isUninstalled == NO) {
_isUninstalled = YES;
[button setTitle:@"install" forState:UIControlStateNormal];
[self.constraint uninstall];
} else {
_isUninstalled = NO;
[button setTitle:@"uninstall" forState:UIControlStateNormal];
[self.constraint install];
}
button.enabled = NO;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
button.enabled = YES;
}];
}
@end
image.png
CompressionResistance
@interface CompressionResistanceViewController ()
@end
@implementation CompressionResistanceViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.layer.borderWidth = 0.5f;
button.layer.borderColor = [UIColor blackColor].CGColor;
button.layer.cornerRadius = 4.f;
[button setTitle:@"CompressionResistanceViewController" forState:UIControlStateNormal];
[self.view addSubview:button];
// 重新设定水平方向上button防挤压适配文本宽度的优先级为500,不设定的话,默认值为750
[button setContentCompressionResistancePriority:500 forAxis:UILayoutConstraintAxisHorizontal];
__block NSString *showString = nil;
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
// 设置宽度为50,如果优先级低于设定的500,设置的宽度50将失效,如果优先级大于500,设置的宽度50有效
CGFloat priority = arc4random() % 2 ? 499 : 501;
make.width.mas_equalTo(50.f).priority(priority);
showString = [NSString stringWithFormat:@"优先级: %.0f %@", priority, priority > 500 ? @"挤压宽度设定有效" : @"挤压宽度设定无效"];
}];
UILabel *label = [UILabel new];
label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
[self.view addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10);
make.bottom.mas_equalTo(-10);
}];
label.text = showString;
}
@end
image.png
image.png
ContentHugging
@interface ContentHuggingViewController ()
@end
@implementation ContentHuggingViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.layer.borderWidth = 0.5f;
button.layer.borderColor = [UIColor blackColor].CGColor;
button.layer.cornerRadius = 4.f;
[button setTitle:@"ContentHuggingViewController" forState:UIControlStateNormal];
[self.view addSubview:button];
// 重新设定水平方向上button超出宽度适配文本宽度的优先级为500,不设定的话,默认值为250
[button setContentHuggingPriority:500 forAxis:UILayoutConstraintAxisHorizontal];
__block NSString *showString = nil;
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
// 设置宽度为300,如果优先级低于设定的500,设置的宽度300将失效,如果优先级大于500,设置的宽度300有效
CGFloat priority = arc4random() % 2 ? 499 : 501;
make.width.mas_equalTo(300.f).priority(priority);
showString = [NSString stringWithFormat:@"优先级: %.0f %@", priority, priority > 500 ? @"超出宽度设定有效" : @"超出宽度设定无效"];
}];
UILabel *label = [UILabel new];
label.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
[self.view addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10);
make.bottom.mas_equalTo(-10);
}];
label.text = showString;
}
@end
image.png
image.png
Layout与Frame混合的自定义view
@interface CustomLayoutMixFrameViewController ()
@end
@implementation CustomLayoutMixFrameViewController
- (void)viewDidLoad {
[super viewDidLoad];
if (arc4random() % 2) {
// Frame形式布局
CustomLayoutView *mixView = [[CustomLayoutView alloc] initWithFrame:CGRectMake(0, 0, Width - 80.f, 100)];
mixView.center = self.view.center;
[self.view addSubview:mixView];
mixView.label.text = @"Frame 脑袋空了半晌后,我突地拿起电话,打电话同领导请假。";
} else {
// Layout形式布局
CustomLayoutView *mixView = [CustomLayoutView new];
[self.view addSubview:mixView];
[mixView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.left.mas_offset(40.f);
make.right.mas_offset(-40.f);
make.height.mas_equalTo(100.f);
}];
mixView.label.text = @"Layout 脑袋空了半晌后,我突地拿起电话,打电话同领导请假。";
}
}
@end
@interface CustomLayoutView ()
@end
@implementation CustomLayoutView
- (instancetype)init {
NSLog(@"[CustomLayoutView new]");
if (self = [super init]) {
[self initSubViews];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
NSLog(@"[[CustomLayoutView alloc] initWithFrame:frame]");
if (self = [super initWithFrame:frame]) {
[self initSubViews];
}
return self;
}
- (void)initSubViews {
self.layer.borderWidth = 0.5f;
self.layer.borderColor = [UIColor redColor].CGColor;
if (!self.label) {
// 传统frame模式的label
self.label = [[UILabel alloc] initWithFrame:CGRectZero];
self.label.layer.borderWidth = 0.5f;
self.label.numberOfLines = 0;
self.label.layer.borderColor = [UIColor greenColor].CGColor;
self.label.top = 10.f;
self.label.left = 10.f;
[self addSubview:self.label];
}
}
- (void)layoutSubviews {
[super layoutSubviews];
// 只影响frame形式的布局
self.label.width = self.width - 20.f;
[self.label sizeToFit];
}
@end
image.png
image.png
IntrinsicContent
@interface IntrinsicContentViewController ()
@property (nonatomic, strong) IntrinsicContentSizeView *wrappingView;
@end
@implementation IntrinsicContentViewController
- (void)viewDidLoad {
[super viewDidLoad];
// http://devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html
// 通知中心(检测屏幕旋转)
self.notificationCenter = [DefaultNotificationCenter defaultNotificationCenterWithDelegate:self addNotificationNames:^(NSMutableArray<NSString *> *names) {
[names addObject:UIApplicationDidChangeStatusBarOrientationNotification];
}];
self.wrappingView = [IntrinsicContentSizeView new];
self.wrappingView.layer.borderWidth = 0.5f;
self.wrappingView.layer.borderColor = [UIColor redColor].CGColor;
self.wrappingView = self.wrappingView;
[self.view addSubview:self.wrappingView];
[self.wrappingView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
}];
self.wrappingView.itemCount = arc4random() % 100 + 4;
self.wrappingView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 100;
// 按钮
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"Change ItemCount" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonsEvent:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
[button mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(-10.f);
make.left.mas_equalTo(10.f);
}];
}
- (void)defaultNotificationCenter:(DefaultNotificationCenter *)notification name:(NSString *)name object:(id)object {
if ([name isEqualToString:UIApplicationDidChangeStatusBarOrientationNotification]) {
// 屏幕旋转后重新设置最大宽度
self.wrappingView.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 100;
}
}
#pragma mark -
- (void)buttonsEvent:(UIButton *)button {
self.wrappingView.itemCount = arc4random() % 100 + 4;
}
static const CGSize itemSize = {20, 12};
@implementation IntrinsicContentSizeView
#pragma mark - Setter method.
- (void)setItemCount:(NSInteger)itemCount {
_itemCount = itemCount;
// 删除所有的subView
while (self.subviews.count) {
[self.subviews.lastObject removeFromSuperview];
}
// 添加view
for (int i = 0; i < _itemCount; i++) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemSize.width, itemSize.height)];
view.backgroundColor = [UIColor colorWithHue:((13 + i * 17) % 255) / 255. saturation:1 brightness:1 alpha:1.0];
// 不支持约束,所有的布局在-layoutSubviews中用setFrame的方式
view.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:view];
// 显示的文本
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:10.f];
label.text = [NSString stringWithFormat:@"%d", i + 1];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
[view addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.top.mas_equalTo(0);
make.size.mas_equalTo(CGSizeMake(itemSize.width, itemSize.height));
}];
}
// 通知布局系统让固有的内容尺寸失效,接下来系统会从intrinsicContentSize方法中读取新的固有的尺寸
[self invalidateIntrinsicContentSize];
}
- (void)setPreferredMaxLayoutWidth:(CGFloat)width {
// 如果设定的最大宽度与自己的最大宽度相等,则不做任何操作
if (self.preferredMaxLayoutWidth == width) {
return;
}
_preferredMaxLayoutWidth = width;
// 通知布局系统让固有的内容尺寸失效,接下来系统会从intrinsicContentSize方法中读取新的固有的尺寸
[self invalidateIntrinsicContentSize];
}
#pragma mark - Private method.
/**
根据给定的总宽度,计算每一个子view的frame的尺寸
@param layoutWidth 给定的宽度
@param block 每一个子view的frame值
*/
- (void)enumerateItemRectsForLayoutWidth:(CGFloat)layoutWidth usingBlock:(void (^)(CGRect itemRect))block {
CGFloat x = 0;
CGFloat y = 0;
for (NSUInteger i = 0; i < self.itemCount; i++) {
if (x + itemSize.width > layoutWidth) {
y += itemSize.height;
x = 0;
}
block(CGRectMake(x, y, itemSize.width, itemSize.height));
x += itemSize.width;
}
}
#pragma mark - Overwrite system method.
- (CGSize)intrinsicContentSize {
if (self.itemCount == 0) {
return CGSizeZero;
}
__block CGRect totalRect = CGRectNull;
[self enumerateItemRectsForLayoutWidth:self.preferredMaxLayoutWidth usingBlock:^(CGRect itemRect) {
// 获取融合的rect值
totalRect = CGRectUnion(itemRect, totalRect);
}];
return totalRect.size;
}
- (void)layoutSubviews {
[super layoutSubviews];
NSEnumerator *subviewEnumerator = [self.subviews objectEnumerator];
[self enumerateItemRectsForLayoutWidth:self.preferredMaxLayoutWidth usingBlock:^(CGRect itemRect) {
// 给每一个子view设定尺寸
[[subviewEnumerator nextObject] setFrame:itemRect];
}];
}
@end
image.png
BaselineLayoutView
@interface BaselineLayoutViewController ()
@end
@implementation BaselineLayoutViewController
- (void)viewDidLoad {
[super viewDidLoad];
// BaselineLayoutView 01
BaselineLayoutView *baseLineView_01 = [BaselineLayoutView baselineLayoutViewWithString:@"不知从什么时候开始,对一片沉寂的冬天,以及纷扬洁白的雪花,生出了一种极其厌恶的情绪。"
image:[UIImage imageNamed:@"baseLineView_01"]];
[self.view addSubview:baseLineView_01];
[baseLineView_01 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.view);
make.left.mas_equalTo(10);
}];
// BaselineLayoutView 02
BaselineLayoutView *baseLineView_02 = [BaselineLayoutView baselineLayoutViewWithString:@"青春年少,任性而潇洒,像森林里一排不甘在下的幼林,倔强的生长,寻觅属于自己的广阔天空。"
image:[UIImage imageNamed:@"baseLineView_02"]];
[self.view addSubview:baseLineView_02];
[baseLineView_02 mas_makeConstraints:^(MASConstraintMaker *make) {
make.baseline.equalTo(baseLineView_01.mas_baseline);
make.right.mas_equalTo(-10.f);
}];
}
@end
@interface BaselineLayoutView ()
@property (nonatomic, strong) NSString *string;
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIImageView *imageView;
@end
@implementation BaselineLayoutView
+ (instancetype)baselineLayoutViewWithString:(NSString *)string image:(UIImage *)image {
BaselineLayoutView *view = [[self class] new];
view.string = string;
view.image = image;
[view initSubViews];
return view;
}
- (void)initSubViews {
self.backgroundColor = [UIColor lightGrayColor];
// 图片
self.imageView = [[UIImageView alloc] initWithImage:self.image];
[self addSubview:self.imageView];
[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10);
make.top.mas_equalTo(10);
make.right.mas_equalTo(-10);
}];
// 以iamgeView的尺寸作为高优先级进行布局
[self.imageView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.imageView setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
// 文本
self.label = [UILabel new];
self.label.numberOfLines = 0;
self.label.font = [UIFont systemFontOfSize:12.f];
self.label.textColor = [UIColor whiteColor];
self.label.text = self.string;
[self addSubview:self.label];
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(10);
make.top.mas_equalTo(self.imageView.mas_bottom).offset(10);
make.right.mas_equalTo(-10);
make.bottom.mas_equalTo(self.mas_bottom).offset(-10);
}];
}
#pragma mark - Overwrite
- (UIView *)viewForLastBaselineLayout {
return self.imageView;
}
@end
image.png
多样式cell
interface MultiStyleCell ()
@property (nonatomic, strong) UILabel *companyLabel;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *addressLabel;
@end
@implementation MultiStyleCell
- (void)setupCell {
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0).priorityHigh();
make.top.mas_equalTo(0).priorityHigh();
make.right.mas_equalTo(0).priorityHigh();
}];
}
- (void)buildSubview {
UIView *line = [UIView new];
line.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5f];
[self.contentView addSubview:line];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.bottom.mas_equalTo(0);
make.right.mas_equalTo(0);
make.height.mas_equalTo(0.5);
}];
self.companyLabel = [UILabel new];
self.companyLabel.numberOfLines = 0;
self.companyLabel.font = [UIFont systemFontOfSize:22];
[self.contentView addSubview:self.companyLabel];
self.nameLabel = [UILabel new];
self.nameLabel.numberOfLines = 0;
self.nameLabel.font = [UIFont systemFontOfSize:18];
[self.contentView addSubview:self.nameLabel];
self.addressLabel = [UILabel new];
self.addressLabel.numberOfLines = 0;
self.addressLabel.font = [UIFont systemFontOfSize:14.f];
self.addressLabel.textColor = [UIColor lightGrayColor];
[self.contentView addSubview:self.addressLabel];
}
- (void)loadContent {
self.companyLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 30.f;
self.nameLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 30.f;
self.addressLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 30.f;
MultiStyleModel *model = self.data;
UIView *supperView = self.contentView;
self.companyLabel.text = model.company;
self.nameLabel.text = model.userName;
self.addressLabel.text = model.address;
// companyLabel位置依赖于contentView,如果没有值,则紧贴着contentView的顶部
[self.companyLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
if (model.company.length > 0) {
make.top.mas_equalTo(15.f);
make.left.mas_equalTo(15.f);
} else {
make.top.mas_equalTo(0);
make.left.mas_equalTo(0);
make.height.mas_equalTo(0);
}
make.bottom.lessThanOrEqualTo(supperView).offset(-15.f);
}];
// nameLabel位置依赖于companyLabel,如果没有值,则紧贴着companyLabel的顶部
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
if (model.userName.length > 0) {
make.top.mas_equalTo(self.companyLabel.mas_bottom).offset(15.f);
make.left.mas_equalTo(15.f);
} else {
make.top.mas_equalTo(self.companyLabel.mas_bottom).offset(0.f);
make.left.mas_equalTo(0);
make.height.mas_equalTo(0);
}
make.bottom.lessThanOrEqualTo(supperView).offset(-15.f);
}];
// addressLabel位置依赖于nameLabel,如果没有值,则紧贴着nameLabel的顶部
[self.addressLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
if (model.address.length > 0) {
make.top.mas_equalTo(self.nameLabel.mas_bottom).offset(15.f);
make.left.mas_equalTo(15.f);
} else {
make.top.mas_equalTo(self.nameLabel.mas_bottom).offset(0.f);
make.left.mas_equalTo(0);
make.height.mas_equalTo(0);
}
make.bottom.lessThanOrEqualTo(supperView).offset(-15.f);
}];
}
@end
image.png
网友评论