iOS:Masonry 英文原档介绍

Masonry 英文原档介绍:

Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you‘re using Swift in your project, we recommend using SnapKit as it provides better type safety with a simpler API.

Masonry is a light-weight layout framework which wraps AutoLayout with a nicer syntax. Masonry has its own layout DSL which provides a chainable way of describing your NSLayoutConstraints which results in layout code that is more concise and readable. Masonry supports iOS and Mac OS X.

For examples take a look at the Masonry iOS Examples project in the Masonry workspace. You will need to run pod install after downloading.

What‘s wrong with NSLayoutConstraints?

Under the hood Auto Layout is a powerful and flexible way of organising and laying out your views. However creating constraints from code is verbose and not very descriptive. Imagine a simple example in which you want to have a view fill its superview but inset by 10 pixels on every side

UIView *superview = self;
UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
view1.backgroundColor = [UIColor greenColor];
[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

    //view1 constraints
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeLeft
                                multiplier:1.0
                                  constant:padding.left],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:-padding.bottom],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeRight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:-padding.right],

 ]];

Even with such a simple example the code needed is quite verbose and quickly becomes unreadable when you have more than 2 or 3 views. Another option is to use Visual Format Language (VFL), which is a bit less long winded. However the ASCII type syntax has its own pitfalls and its also a bit harder to animate as NSLayoutConstraint constraintsWithVisualFormat: returns an array.

Prepare to meet your Maker!

Heres the same constraints created using MASConstraintMaker

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
    make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];

Or even shorter

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];

Also note in the first example we had to add the constraints to the superview [superview addConstraints:.... Masonry however will automagically add constraints to the appropriate view.

Masonry will also call view1.translatesAutoresizingMaskIntoConstraints = NO; for you.

Not all things are created equal

.equalTo equivalent to NSLayoutRelationEqual

.lessThanOrEqualTo equivalent to NSLayoutRelationLessThanOrEqual

.greaterThanOrEqualTo equivalent to NSLayoutRelationGreaterThanOrEqual

These three equality constraints accept one argument which can be any of the following:

1. MASViewAttribute

make.centerX.lessThanOrEqualTo(view2.mas_left);
MASViewAttribute NSLayoutAttribute
view.mas_left NSLayoutAttributeLeft
view.mas_right NSLayoutAttributeRight
view.mas_top NSLayoutAttributeTop
view.mas_bottom NSLayoutAttributeBottom
view.mas_leading NSLayoutAttributeLeading
view.mas_trailing NSLayoutAttributeTrailing
view.mas_width NSLayoutAttributeWidth
view.mas_height NSLayoutAttributeHeight
view.mas_centerX NSLayoutAttributeCenterX
view.mas_centerY NSLayoutAttributeCenterY
view.mas_baseline NSLayoutAttributeBaseline

2. UIView/NSView

if you want view.left to be greater than or equal to label.left :

//these two constraints are exactly the same
make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);

3. NSNumber

Auto Layout allows width and height to be set to constant values. if you want to set view to have a minimum and maximum width you could pass a number to the equality blocks:

//width >= 200 && width <= 400
make.width.greaterThanOrEqualTo(@200);
make.width.lessThanOrEqualTo(@400)

However Auto Layout does not allow alignment attributes such as left, right, centerY etc to be set to constant values. So if you pass a NSNumber for these attributes Masonry will turn these into constraints relative to the view’s superview ie:

//creates view.left = view.superview.left + 10
make.left.lessThanOrEqualTo(@10)

Instead of using NSNumber, you can use primitives and structs to build your constraints, like so:

make.top.mas_equalTo(42);
make.height.mas_equalTo(20);
make.size.mas_equalTo(CGSizeMake(50, 100));
make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));
make.left.mas_equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));

By default, macros which support autoboxing are prefixed with mas_. Unprefixed versions are available by defining MAS_SHORTHAND_GLOBALS before importing Masonry.

4. NSArray

An array of a mixture of any of the previous types

make.height.equalTo(@[view1.mas_height, view2.mas_height]);
make.height.equalTo(@[view1, view2]);
make.left.equalTo(@[view1, @100, view3.right]);

Learn to prioritize

.priority allows you to specify an exact priority

.priorityHigh equivalent to UILayoutPriorityDefaultHigh

.priorityMedium is half way between high and low

.priorityLow equivalent to UILayoutPriorityDefaultLow

Priorities are can be tacked on to the end of a constraint chain like so:

make.left.greaterThanOrEqualTo(label.mas_left).with.priorityLow();

make.top.equalTo(label.mas_top).with.priority(600);

Composition, composition, composition

Masonry also gives you a few convenience methods which create multiple constraints at the same time. These are called MASCompositeConstraints

edges

// make top, left, bottom, right equal view2
make.edges.equalTo(view2);

// make top = superview.top + 5, left = superview.left + 10,
//      bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))

size

// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))

center

// make centerX and centerY = button1
make.center.equalTo(button1)

// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))

You can chain view attributes for increased readability:

// All edges but the top should equal those of the superview
make.left.right.and.bottom.equalTo(superview);
make.top.equalTo(otherView);

Hold on for dear life

Sometimes you need modify existing constraints in order to animate or remove/replace constraints. In Masonry there are a few different approaches to updating constraints.

1. References

You can hold on to a reference of a particular constraint by assigning the result of a constraint make expression to a local variable or a class property. You could also reference multiple constraints by storing them away in an array.

// in public/private interface
@property (nonatomic, strong) MASConstraint *topConstraint;

...

// when making constraints
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
}];

...
// then later you can call
[self.topConstraint uninstall];

2. mas_updateConstraints

Alternatively if you are only updating the constant value of the constraint you can use the convience method mas_updateConstraints instead of mas_makeConstraints

// this is Apple‘s recommended place for adding/updating constraints
// this method can get called multiple times in response to setNeedsUpdateConstraints
// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints
- (void)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];
}

3. mas_remakeConstraints

mas_updateConstraints is useful for updating a set of constraints, but doing anything beyond updating constant values can get exhausting. That‘s where mas_remakeConstraints comes in.

mas_remakeConstraints is similar to mas_updateConstraints, but instead of updating constant values, it will remove all of its contraints before installing them again. This lets you provide different constraints without having to keep around references to ones which you want to remove.

- (void)changeButtonPosition {
    [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);
        }
    }];
}

You can find more detailed examples of all three approaches in the Masonry iOS Examples project.

When the ^&*[email protected] hits the fan!

Laying out your views doesn‘t always goto plan. So when things literally go pear shaped, you don‘t want to be looking at console output like this:

Unable to simultaneously satisfy constraints.....blah blah blah....
(
    "<NSLayoutConstraint:0x7189ac0 V:[UILabel:0x7186980(>=5000)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x839ea20 h=--& v=--& V:[MASExampleDebuggingView:0x7186560(416)]>",
    "<NSLayoutConstraint:0x7189c70 UILabel:0x7186980.bottom == MASExampleDebuggingView:0x7186560.bottom - 10>",
    "<NSLayoutConstraint:0x7189560 V:|-(1)-[UILabel:0x7186980]   (Names: ‘|‘:MASExampleDebuggingView:0x7186560 )>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7189ac0 V:[UILabel:0x7186980(>=5000)]>

Masonry adds a category to NSLayoutConstraint which overrides the default implementation of - (NSString *)description. Now you can give meaningful names to views and constraints, and also easily pick out the constraints created by Masonry.

which means your console output can now look like this:

Unable to simultaneously satisfy constraints......blah blah blah....
(
    "<NSAutoresizingMaskLayoutConstraint:0x8887740 MASExampleDebuggingView:superview.height == 416>",
    "<MASLayoutConstraint:ConstantConstraint UILabel:messageLabel.height >= 5000>",
    "<MASLayoutConstraint:BottomConstraint UILabel:messageLabel.bottom == MASExampleDebuggingView:superview.bottom - 10>",
    "<MASLayoutConstraint:ConflictingConstraint[0] UILabel:messageLabel.top == MASExampleDebuggingView:superview.top + 1>"
)

Will attempt to recover by breaking constraint
<MASLayoutConstraint:ConstantConstraint UILabel:messageLabel.height >= 5000>

For an example of how to set this up take a look at the Masonry iOS Examples project in the Masonry workspace.

Installation

Use the orsome CocoaPods.

In your Podfile

pod ‘Masonry‘

If you want to use masonry without all those pesky ‘mas_‘ prefixes. Add #define MAS_SHORTHAND to your prefix.pch before importing Masonry

#define MAS_SHORTHAND

Get busy Masoning

#import "Masonry.h"

Code Snippets

Copy the included code snippets to ~/Library/Developer/Xcode/UserData/CodeSnippets to write your masonry blocks at lightning speed!

mas_make -> [<view> mas_makeConstraints:^(MASConstraintMaker *make){<code>}];

mas_update -> [<view> mas_updateConstraints:^(MASConstraintMaker *make){<code>}];

mas_remake -> [<view> mas_remakeConstraints:^(MASConstraintMaker *make){<code>}];

Features

  • Not limited to subset of Auto Layout. Anything NSLayoutConstraint can do, Masonry can do too!
  • Great debug support, give your views and constraints meaningful names.
  • Constraints read like sentences.
  • No crazy macro magic. Masonry won‘t pollute the global namespace with macros.
  • Not string or dictionary based and hence you get compile time checking.

TODO

  • Eye candy
  • Mac example project
  • More tests and examples
时间: 2024-10-10 21:11:56

iOS:Masonry 英文原档介绍的相关文章

iOS:Masonry介绍与使用

Masonry介绍与使用实践:快速上手Autolayout frame----->autoresing------->autoLayout-------->sizeClasses 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时代 window的size固定为(320,480) 我们只需要简单计算一下相对位置就好了 在iphone4-iphone4s时代 苹果推出了retina屏 但是给了码农们非常大的福利:window的size不变 在iphone

Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库)

Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库) 这是英文文档的第二部分(2):DRAWEE GUIDE 由于第二部分内容多一些,所以分为2个文章发.方便大家查看. Using the ControllerBuilder SimpleDraweeView has two methods for specifying an image. The easy way is to just callsetImageURI. If you wa

Android Fresco图片处理库用法API英文原文文档1(Facebook开源Android图片库)

Fresco是Facebook最新推出的一款用于Android应用中展示图片的强大图片库,可以从网络.本地存储和本地资源中加载图片.其中的Drawees可以显示占位符,直到图片加载完成.而当图片从屏幕上消失时,会自动释放内存. 功能很强大,为了大家学习方便,我将英文原文文档给大家迁移过来,供参考学习. 这是英文文档的第一部分:QUICK START QUICK START Adding Fresco to your Project Here's how to add Fresco to your

0516.32款iOS开发插件和工具介绍[效率]

插件和工具介绍内容均收集于网络,太多了就不一一注明了,在此谢过! 1.Charles 为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析.Charles通过将自己设置成系统的网络访问代理服务器,使得所有的网络访问请求都通过它来完成,从而实现了网络封包的截取和分析.一个可查看所有HTTP和SSL/HTTPS流量的工具.这款工具对于你测试和服务器端进行交互的应用非常有用 2.xScope xScope带有六种不同的工具,帮助每一个设计者快速.精确的完成工作,这些工具功能灵活.强大,包括∶量

IOS常用的系统文件目录介绍

iOS常用目录整理说明是本文要介绍的内容,虽然不同API全面,也算是在编程中常用到的存放目录,所以是必备文档,不多说,来看详细内容讲解. 1.[/Applications] 常用软件的安装目录 内建软体及JB软体存放位置 2. [/private /var/ mobile/Media /iphone video Recorder] 录像文件存放目录 3.[/private /var/ mobile/Media /DCIM] 相机拍摄的照片文件存放目录 4.[/private/var/ mobil

(译)IOS block编程指南 1 介绍

Introduction(介绍) Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block ca

IOS开发网络篇—XML介绍

iOS开发网络篇—XML介绍 一.XML简单介绍 XML:全称是Extensible Markup Language,译作“可扩展标记语言” 跟JSON一样,也是常用的一种用于交互的数据格式,一般也叫XML文档(XML Document) XML举例 <videos> <video name="小黄人 第01部" length="30" /> <video name="小黄人 第02部" length="1

iOS 9应用开发教程之创建iOS 9项目与模拟器介绍

iOS 9应用开发教程之创建iOS 9项目与模拟器介绍 编写第一个iOS 9应用 本节将以一个iOS 9应用程序为例,为开发者讲解如何使用Xcode 7.0去创建项目,以及iOS模拟器的一些功能.编辑界面等内容. 创建iOS 9项目 一个iOS应用的所有文件都在一个Xcode项目下.项目可以帮助用户管理代码文件和资源文件.以下是使用Xcode创建项目的具体操作步骤 (1)打开Xcode,弹出Welcome to Xcode对话框,如图1.4所示. 图1.4  Welcome to Xcode对话

IOS 开启定位功能 CLLocationManager 介绍-简单使用

iOS 中的定位功能,主要在 CoreLocation库中,需要用到位置管理器 CLLocationManager 来完成绝大多数事情. 要使用 CLLocationManager 首先需要一个对象~ 以及对它进行简单的设置,最后开启定位功能, 就开始定位了,定位成功或者失败后都会调用代理方法返回信息 1 CLLocationManager *manger; 2 3 manger = [[CLLocationManager alloc] init]; //初始化 4 5 manger.deleg