Masonry框架学习

作者: 肥猫记 | 来源:发表于2016-07-03 20:59 被阅读370次

    Masonry

    使用

    • 关键方法:- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
    • 约束方法除了equalTo,还有lessThanOrEqualTo和greaterThanOrEqualTo
    • 当已有约束需要更新时调用mas_updateConstraints方法
    • mas_remakeConstraints方法会先清除当前所有约束再布置
    • Masonry的五大参数:Attribute(属性) ,Relation(关系),Multiplier(乘),Constant(大小),Priority(优先级)
        //一个系统的约束创建方法
        [NSLayoutConstraint constraintWithItem:view1
                                     attribute:NSLayoutAttributeTop
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:superview
                                     attribute:NSLayoutAttributeTop
                                    multiplier:1.0
                                      constant:padding.top]
                                      
        //mas_makeConstraints
        [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(superView).with.offset(10);
            make.left.equalTo(superView).with.offset(10);
            make.bottom.equalTo(superView.mas_bottom).with.offset(-10);
            make.right.equalTo(superView.mas_right).with.offset(-10);
    //        等价于
    //        make.edges.equalTo(superView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
    //        会自动调用view1.translatesAutoresizingMaskIntoConstraints = NO;
        }];
        //mas_remakeConstrains
        [self.button mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.size.equalTo(self.buttonSize);
    
            if (topLeft) {
                make.top.and.left.offset(10);
            } else {
                make.bottom.and.right.offset(-10);
            }
        }];
        //mas_updateConstraints
            [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(self);
            make.width.equalTo(@(self.buttonSize.width)).priorityLow();
            make.height.equalTo(@(self.buttonSize.height)).priorityLow();
            make.width.lessThanOrEqualTo(self);
            make.height.lessThanOrEqualTo(self);
        }];
    
        //according to apple super should be called at end of method
        [super updateConstraints];
    }
    

    原理

    • mas_makeConstraints方法内部创建MASConstraintMaker对象,然后传递到block执行,完成后调用maker的install方法来确保约束被添加到视图中
    //设置约束方法
    - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block {
        self.translatesAutoresizingMaskIntoConstraints = NO;
        MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
        constraintMaker.updateExisting = YES;
        block(constraintMaker);
        return [constraintMaker install];
    }
    //MASConstraintMaker的install方法
    - (NSArray *)install {
        //判断是否有移除所有已存在的约束标志
        if (self.removeExisting) {
            NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
            for (MASConstraint *constraint in installedConstraints) {
                [constraint uninstall];
            }
        }
        //取出maker对象中的所有约束
        NSArray *constraints = self.constraints.copy;
        for (MASConstraint *constraint in constraints) {
        //设置已经设置了约束的标志
            constraint.updateExisting = self.updateExisting;
            //调用MASConstraint的install方法
            [constraint install];
        }
        [self.constraints removeAllObjects];
        return constraints;
    }
    //MASViewConstraint(MASConstraint子类)的install方法
    - (void)install {
        ...
        ...
        MASLayoutConstraint *layoutConstraint
            = [MASLayoutConstraint constraintWithItem:firstLayoutItem
                                            attribute:firstLayoutAttribute
                                            relatedBy:self.layoutRelation
                                               toItem:secondLayoutItem
                                            attribute:secondLayoutAttribute
                                           multiplier:self.layoutMultiplier
                                             constant:self.layoutConstant];
        
        ...
        ...
        MASLayoutConstraint *existingConstraint = nil;
        if (self.updateExisting) {
            existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint];
        }
        if (existingConstraint) {
            // just update the constant
            existingConstraint.constant = layoutConstraint.constant;
            self.layoutConstraint = existingConstraint;
        } else {
            //调用系统方法添加约束
            [self.installedView addConstraint:layoutConstraint];
            self.layoutConstraint = layoutConstraint;
            [firstLayoutItem.mas_installedConstraints addObject:self];
        }
    }
    

    MASConstraint和其子类

    • MASConstraint提供了基础属性(left,top,leftMargin...),且是创建链式语法的必要要素
    • MASCompositeConstraint内有一个childConstraints的属性,在布局的时候,会遍历该数组,逐一进行install方法调用,make.edges,make.size返回的就是该类型
    • MASViewConstraint是承载支持AutoLayout真正的对象,他创建了一个NSLayoutConstraint的必要属性,并将其添加到对应的view上;它的firstViewAttribute和secondViewAttribute属性分别代表了对应要设置约束两个view的属性

    Masonry链式语法实现原理

    进入文件中可发现left,top..等maker属性方法返回都是MASConstraint类型,而MASConstraint中也有这些相同的属性方法,返回值依是MASCompositeConstraint对象,所有才能像make.top.left.right...这样使用Masonry,具体实现原理如下

     1、MASConstraint的left方法:
    
        - (MASConstraint *)left {
            return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
        }
        它会跳转到MASViewConstraint的addConstraintWithLayout...方法
    --------------------------------------------    
        2、MASViewConstraint的addConstraintWithLayout...方法
    
        - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
            return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
        }
        它会调用delegate的constraint...delegate就是MASConstraintMaker,来看看吧
    --------------------------------------------
        3、MASConstraintMaker的代理方法
    
        - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
                MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
                [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
                return compositeConstraint;
        }
        创建的compositeConstraint布局时,就会调用children的install方法设置约束,从而达到通过点语法
    
    

    相关文章

      网友评论

        本文标题:Masonry框架学习

        本文链接:https://www.haomeiwen.com/subject/vxdcjttx.html