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
.equalToequivalent to NSLayoutRelationEqual
.lessThanOrEqualToequivalent to NSLayoutRelationLessThanOrEqual
.greaterThanOrEqualToequivalent 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
.priorityallows you to specify an exact priority
.priorityHighequivalent to UILayoutPriorityDefaultHigh
.priorityMediumis half way between high and low
.priorityLowequivalent 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 ^&*!@ 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
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
iOS:Masonry 英文原档介绍的更多相关文章
- iOS:Masonry介绍与使用
Masonry介绍与使用实践:快速上手Autolayout frame----->autoresing------->autoLayout-------->sizeClasses ...
- iOS 9应用开发教程之创建iOS 9项目与模拟器介绍
iOS 9应用开发教程之创建iOS 9项目与模拟器介绍 编写第一个iOS 9应用 本节将以一个iOS 9应用程序为例,为开发者讲解如何使用Xcode 7.0去创建项目,以及iOS模拟器的一些功能.编辑 ...
- (译)IOS block编程指南 1 介绍
Introduction(介绍) Block objects are a C-level syntactic and runtime feature. They are similar to stan ...
- iOS开发网络篇—简单介绍ASI框架的使用
iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大 ...
- iOS开发UI篇—简单介绍静态单元格的使用
iOS开发UI篇—简单介绍静态单元格的使用 一.实现效果与说明 说明:观察上面的展示效果,可以发现整个界面是由一个tableview来展示的,上面的数据都是固定的,且几乎不会改变. 要完成上面的效果, ...
- iOS开发多线程篇—GCD介绍
iOS开发多线程篇—GCD介绍 一.简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 G ...
- iOS开发官方文档汇总
程序员的学习过程是无止境的,程序员学习的途径是多样的.可以从视频教程中领悟,也可以从他人的代码中 理解.但当我们专注于某一个平台在开发的时候,对于某个API使用或者功能实现有疑问,通常简单的测试可以让 ...
- iOS开发Swift篇—简单介绍
iOS开发Swift篇—简单介绍 一.简介 Swift是苹果于2014年WWDC(苹果开发者大会)发布的全新编程语言 Swift在天朝译为“雨燕”,是它的LOGO 是一只燕子,跟Objective-C ...
- spring-data-solr官方学习文档介绍
spring-data-solr文档介绍如下: 通过http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd(spring ...
随机推荐
- keras_实现cnn_手写数字识别
# conding:utf-8 import os os.environ[' import numpy as np from keras.models import Sequential from k ...
- react+redux基础用法
在学react的是,发现一旦我们封装好了我们的组件,那么我们的项目就跟搭积木一样简单快速,可是我们发现了一个问题,在一个页面往往会嵌套很多的组件,子组件必须要通过父组件传递参数才能渲染出数据,我们回想 ...
- bzoj 1083 最小生成树
裸的最小生成树. /************************************************************** Problem: User: BLADEVIL Lan ...
- linux基础编程 套接字socket 完整的服务器端多线程socket程序【转】
转自:http://blog.csdn.net/ghostyu/article/details/7737203 此段程序来自我的一个项目中,稍微做了些修改,运行稳定,客户端程序比较简单所以未编写,可以 ...
- IC卡的传输协议(2)-块传输协议T=1续【转】
转自:http://bbs.ednchina.com/BLOG_ARTICLE_172025.HTM (3)容错操作 先来看一下容错的规则定义. * 复位应答后,第一个数据块是由终端发往IC卡的,而且 ...
- centos 自启动
https://blog.phpha.com/backup/archives/1458.html 1.服务 chkconfig 服务名 on 查看所有可以 chkconfig --list 2 修改 ...
- grep 所有多个关键字
标签(空格分隔): Linux 多个关键字 或 关系 egrep 'CommentManager|getComment' --color catalina.log.2017-03-15 grep -E ...
- 使用chardet模块判断网页编码
import chardet import urllib.request url='http://stock.sohu.com/news/' html = urllib.request.urlopen ...
- 《锋利的JQuery》读书要点笔记2——DOM操作
第三章 jQuery中的DOM操作 3.1 DOM(Document Object Model)操作的分类 1. DOM Core 例如:document.getElementsByTagNam ...
- ORM-班级信息系统
ORM版学员管理系统 班级表 表结构 class Class(models.Model): id = models.AutoField(primary_key=True) # 主键 cname = m ...