Marsonry库学习笔记

多个相似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);
        // 降低优先度,相当于设置一个最小值
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        // 设置最大值不超过self的宽度/高度
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];
    
    // 最后才调用父方法
    [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则会更新出现在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;

    //再次调用,重新计算
    [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);
    }];
    
    //最后才调用
    [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);
    }];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容