多個相似Controller模板寫法
- (id)initWithTitle:(NSString *)title viewClass:(Class)viewClass {
self = [super init];
if (!self) return nil;
self.title = title;
self.viewClass = viewClass;
return self;
}
- (void)loadView {
self.view = self.viewClass.new;
self.view.backgroundColor = [UIColor whiteColor];
}
基本
MASExampleBasicView
int padding = 10;
[greenView makeConstraints:^(MASConstraintMaker *make) {
// greenView頂部距離父視圖頂部間距>=10
make.top.greaterThanOrEqualTo(superview.top).offset(padding);
// greenView左邊距離父視圖左邊間距==10
make.left.equalTo(superview.left).offset(padding);
// greenView底部距離blueView頂部間距==-10,說明blueView在greenView下方
make.bottom.equalTo(blueView.top).offset(-padding);
// greenView右邊距離redView左邊間距==-10,說明redView在greenView右方
make.right.equalTo(redView.left).offset(-padding);
// greenView寬度==redView寬度
make.width.equalTo(redView.width);
// greenView高度==redView高度
make.height.equalTo(redView.height);
// greenView高度==blue高度
make.height.equalTo(blueView.height);
}];
更新修改
MASExampleUpdateView
+ (BOOL)requiresConstraintBasedLayout {
// 我們應該在自定義View中重寫這個方法猛蔽。如果我們要使用Auto Layout布局當前視圖团甲,應該設置為返回YES弟蚀。
return YES;
}
// 蘋果推薦的更新約束的地方
- (void)updateConstraints {
[self.growingButton updateConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
// 降低優(yōu)先度浴韭,相當于設置一個最小值
make.width.equalTo(@(self.buttonSize.width)).priorityLow();
make.height.equalTo(@(self.buttonSize.height)).priorityLow();
// 設置最大值不超過self的寬度/高度
make.width.lessThanOrEqualTo(self);
make.height.lessThanOrEqualTo(self);
}];
// 最后才調(diào)用父方法
[super updateConstraints];
}
- (void)didTapGrowButton:(UIButton *)button {
self.buttonSize = CGSizeMake(self.buttonSize.width * 1.3, self.buttonSize.height * 1.3);
// 告訴self約束準備更新
[self setNeedsUpdateConstraints];
// 更新約束
[self updateConstraintsIfNeeded];
[UIView animateWithDuration:0.4 animations:^{
// 更新視圖
[self layoutIfNeeded];
}];
}
重設
MASExampleRemakeView
重設使用方法remakeConstraints
remakeConstraints和updateConstraints類似,只是remakeConstraints會刪除舊的約束道媚,添加新的約束
而updateConstraints則會更新出現(xiàn)在block里的約束
使用常量
MASExampleConstantsView
Masonry可以使用標量和結構體(CGPoint揍愁、CGSize之類的)
Edges
MASExampleSidesView
[view mas_makeConstraints:^(MASConstraintMaker *make) {
// 一次設好上下左右間距的方法
make.edges.equalTo(lastView).insets(UIEdgeInsetsMake(5, 10, 15, 20));
}];
AspectFit
MASExampleAspectFitView
//設置約束
[self addSubview:_topView];
[_topView makeConstraints:^(MASConstraintMaker *make) {
make.top.left.and.right.equalTo(self);
}];
[self addSubview:_bottomView];
[_bottomView makeConstraints:^(MASConstraintMaker *make) {
make.left.right.and.bottom.equalTo(self);
make.top.equalTo(_topView.mas_bottom);
make.height.equalTo(_topView.mas_height);
}];
[_topView addSubview:_topInnerView];
[_topInnerView makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(_topInnerView.mas_height).multipliedBy(3);
make.center.equalTo(_topView);
make.width.and.height.lessThanOrEqualTo(_topView);
make.width.and.height.equalTo(_topView).priorityLow();
}];
[_bottomView addSubview:_bottomInnerView];
[_bottomInnerView makeConstraints:^(MASConstraintMaker *make) {
make.height.equalTo(_bottomInnerView.mas_width).multipliedBy(3);
make.center.equalTo(_bottomView);
make.width.and.height.lessThanOrEqualTo(_bottomView);
make.width.and.height.equalTo(_bottomView).priorityLow();
}];
PS:設置約束的時候兩個視圖要在同一父視圖上或者有關系
簡單動畫
MASExampleAnimatedView
- (void)makeConstraints {
int padding = self.padding;
UIEdgeInsets paddingInserts = UIEdgeInsetsMake(padding, padding, padding, padding);
[self.greenView makeConstraints:^(MASConstraintMaker *make) {
[self.animateArray addObjectsFromArray:@[
make.edges.equalTo(self).offset(paddingInserts).priorityLow(),
make.right.equalTo(self.redView.mas_left).offset(-padding),
make.bottom.equalTo(self.blueView.mas_top).offset(-padding)
]
];
make.size.equalTo(self.redView);
make.height.equalTo(self.blueView);
}];
[self.redView makeConstraints:^(MASConstraintMaker *make) {
[self.animateArray addObjectsFromArray:@[
make.edges.equalTo(self).offset(paddingInserts).priorityLow(),
make.bottom.equalTo(self.blueView.mas_top).offset(-padding)
]
];
}];
[self.blueView makeConstraints:^(MASConstraintMaker *make) {
[self.animateArray addObject:make.edges.equalTo(self).offset(paddingInserts).priorityLow()];
}];
}
// 移動到window顯示的時候開始動畫
- (void)didMoveToWindow {
[self layoutIfNeeded];
if (self.window) {
self.isAnimating = YES;
[self anmateWithInvertedInserts:NO];
}
}
- (void)willMoveToWindow:(UIWindow *)newWindow {
self.isAnimating = newWindow != nil;
}
- (void)anmateWithInvertedInserts:(BOOL)invertedInserts {
if (!self.isAnimating) {
return;
}
int padding = invertedInserts ? 100 : self.padding;
UIEdgeInsets paddingInserts = UIEdgeInsetsMake(padding, padding, padding, padding);
// 遍歷之前存儲的約束柏腻、依次修改
for (MASConstraint *constraint in self.animateArray) {
constraint.insets = paddingInserts;
}
// 使用動畫更新視圖
[UIView animateWithDuration:1.0 animations:^{
[self layoutIfNeeded];
} completion:^(BOOL finished) {
[self anmateWithInvertedInserts:!invertedInserts];
}];
}
長文本約束
MASExampleLabelView
主要存在兩種情況
1.右邊短文本势就,左邊長文本辞居。
重寫layoutSubviews方法確定短文本寬度,由此確定長文本寬度蛋勺,設置preferredMaxLayoutWidth
左邊短文本,右邊長文本鸠删。與上面一樣處理
[self.longLabel makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.left).insets(kPadding);
make.top.equalTo(self.top).insets(kPadding);
}];
[self.shortLabel makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.longLabel.centerY);
make.right.equalTo(self.right).insets(kPadding);
}];
- (void)layoutSubviews {
[super layoutSubviews];
// 使用Autolayout抱完,由此方法獲取真實的frame
CGFloat width = CGRectGetMinX(self.shortLabel.frame) - kPadding.left;
width -= CGRectGetMinX(self.longLabel.frame);
self.longLabel.preferredMaxLayoutWidth = width;
//再次調(diào)用,重新計算
[super layoutSubviews];
}
2.上面長文本刃泡,下面固定
- (void)makeConstraints {
UIView *superView = self;
[self.longLabel makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superView.top).offset(kPadding);
make.left.equalTo(superView.left).offset(kPadding);
make.right.equalTo(superView.right).offset(-kPadding);
make.bottom.equalTo(self.shortLabel.top).offset(-kPadding);
}];
[self.shortLabel makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superView).offset(kInserts).priorityLow();
make.left.equalTo(superView.left).offset(kPadding);
}];
}
ScrollView
ScrollView的約束一般是在其上面添加一個contentView通過約束這個contentView來達到效果
- (void)generateContent {
UIView* contentView = UIView.new;
[self.scrollView addSubview:contentView];
[contentView makeConstraints:^(MASConstraintMaker *make) {
// 上下左右與scrollView間距為0巧娱,寬度相同,垂直滾動的scrollView必須確定寬度
make.edges.equalTo(self.scrollView);
make.width.equalTo(self.scrollView);
}];
// 開始計算contentView的高度
UIView *lastView;
CGFloat height = 25;
for (int i = 0; i < 10; i++) {
UIView *view = UIView.new;
view.backgroundColor = [self randomColor];
[contentView addSubview:view];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
[view addGestureRecognizer:singleTap];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(lastView ? lastView.bottom : @0);
make.left.equalTo(@0);
make.width.equalTo(contentView.width);
make.height.equalTo(@(height));
}];
height += 25;
lastView = view;
}
[contentView makeConstraints:^(MASConstraintMaker *make) {
// 對contentView高度進行約束
make.bottom.equalTo(lastView.bottom);
}];
}
Array
多個view對齊的約束
- (void)updateConstraints {
[self.buttonViews updateConstraints:^(MASConstraintMaker *make) {
// 添加baseline對齊
make.baseline.equalTo(self.mas_centerY).with.offset(self.offset);
}];
//最后才調(diào)用
[super updateConstraints];
}
AttributeChaining
鏈式語法
[greenView mas_makeConstraints:^(MASConstraintMaker *make) {
// chain attributes
make.top.and.left.equalTo(superview).insets(padding);
// 相當于
// make.top.greaterThanOrEqualTo(superview).insets(padding);
// make.left.greaterThanOrEqualTo(superview).insets(padding);
make.bottom.equalTo(blueView.mas_top).insets(padding);
make.right.equalTo(redView.mas_left).insets(padding);
make.width.equalTo(redView.mas_width);
make.height.equalTo(@[redView, blueView]);
}];
間距
利用預先設定好的間距布局
view.layoutMargins = UIEdgeInsetsMake(5, 10, 15, 20);
[self addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(lastView.topMargin);
make.bottom.equalTo(lastView.bottomMargin);
make.left.equalTo(lastView.leftMargin);
make.right.equalTo(lastView.rightMargin);
}];
多個控件固定間隔的等間隔排列
MASExampleDistributeView
/**
* 多個控件固定間隔的等間隔排列,變化的是控件的長度或者寬度值
*
* @param axisType 軸線方向
* @param fixedSpacing 間隔大小
* @param leadSpacing 頭部間隔
* @param tailSpacing 尾部間隔
*/
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
withFixedSpacing:(CGFloat)fixedSpacing l
eadSpacing:(CGFloat)leadSpacing
tailSpacing:(CGFloat)tailSpacing;
/**
* 多個固定大小的控件的等間隔排列,變化的是間隔的空隙
*
* @param axisType 軸線方向
* @param fixedItemLength 每個控件的固定長度或者寬度值
* @param leadSpacing 頭部間隔
* @param tailSpacing 尾部間隔
*/
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
withFixedItemLength:(CGFloat)fixedItemLength
leadSpacing:(CGFloat)leadSpacing
tailSpacing:(CGFloat)tailSpacing;
LayoutGuide
MASExampleLayoutGuideViewController
[topView makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_topLayoutGuide);
make.left.equalTo(self.view);
make.right.equalTo(self.view);
make.height.equalTo(@40);
}];
[topSubview makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_topLayoutGuide);
make.centerX.equalTo(@0);
make.width.equalTo(@20);
make.height.equalTo(@20);
}];
[bottomView makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.mas_bottomLayoutGuide);
make.left.equalTo(self.view);
make.right.equalTo(self.view);
make.height.equalTo(@40);
}];