1.程序中导入 Masonry 库,并在需要使用的文件中添加头文件 Masonry.h
2.在使用Masonry 添加约束之前,一定要先将你需要添加的约束控件添加到父视图中.
否则直接CRASH
reason: 'couldn't find a common superview for <UIView: 0x7ffa29d2c2c0; frame = (0 0; 0 0);
layer = <CALayer: 0x7ffa29d25e70>> and <UIView: 0x7ffa29d23640; frame = (0 0; 414 736);
autoresize = W+H; layer = <CALayer: 0x7ffa29d15670>>'
3.在Masonry中我们主要使用的就是下面这三个方法
//
使用
mas_makeConstraints
创建
constraint
后,你可以使用局部变量或属性来保存以便下次引用它;如果创建多个
constraints
,你可以采用数组来保存它们
- (
NSArray
*)mas_makeConstraints:(
void
(^)(
MASConstraintMaker
*))block {
}
//
有时你需要更新
constraint(
例如,动画和调试
)
而不是创建固定
constraint
,可以使用
mas_updateConstraints
方法
- (
NSArray
*)mas_updateConstraints:(
void
(^)(
MASConstraintMaker
*))block {
}
//mas_remakeConstraints
与
mas_updateConstraints
比较相似,都是更新
constraint
。不过,
mas_remakeConstraints
是删除之前
constraint
,然后再添加新的
constraint(
适用于移动动画
)
;而
mas_updateConstraints
只是更新
constraint
的值
- (
NSArray
*)mas_remakeConstraints:(
void
(^)(
MASConstraintMaker
*make))block {
}
4.关于添加约束中要使用的属性,主要有下面几种
补充一下
NSLayoutAttributeLeft/NSLayoutAttributeRight 和 NSLayoutAttributeLeading/NSLayoutAttributeTrailing的区别是left/right永远是指左右,而leading/trailing在某些从右至左习惯的地区会变成,leading是右边,trailing是左边
并且在 iOS8 出现之后,又添加了许多的属性.
typedef
NS_ENUM
(NSInteger, NSLayoutAttribute) {
NSLayoutAttributeLeft = 1 ,
NSLayoutAttributeRight,
NSLayoutAttributeTop,
NSLayoutAttributeBottom,
NSLayoutAttributeLeading,
NSLayoutAttributeTrailing,
NSLayoutAttributeWidth,
NSLayoutAttributeHeight,
NSLayoutAttributeCenterX,
NSLayoutAttributeCenterY,
NSLayoutAttributeBaseline,
NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline ,
NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeNotAnAttribute = 0
NSLayoutAttributeLeft = 1 ,
NSLayoutAttributeRight,
NSLayoutAttributeTop,
NSLayoutAttributeBottom,
NSLayoutAttributeLeading,
NSLayoutAttributeTrailing,
NSLayoutAttributeWidth,
NSLayoutAttributeHeight,
NSLayoutAttributeCenterX,
NSLayoutAttributeCenterY,
NSLayoutAttributeBaseline,
NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline ,
NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS ( 8 _0),
NSLayoutAttributeNotAnAttribute = 0
};
有的同学可能会有疑问,新添加的属性和之前的属性好像没有什么区别呀
这里我采用可视化的方法展示.
在界面上布置一个 Label ,对它添加约束.这时候应该是这个样子
但是,我们打开界面右下方的Pin , 发现这里为什么有一个勾选呢? 如果我们去掉勾选添加约束呢?
这时候我们能看到,可以正常添加属性,同时这两个约束也同时存在,查看约束属性,发现属性名称也是相同,但是具体数值却不同.接下来往下看.
细心同学可能已经发现了,在左侧的数值一栏显示的名称不一样.
这里就提到 iOS 8 里添加的属性 --
margins ,
如果你点了constrain to margins,左右会有8个点的空挡,而是从8个点后开始计算约束,而没有点时,已屏幕的0点开始计算。
这里需要注意一点,如果你的视图是 StroyBoard, 那么你的 margins 属性会给你在左右偏移20像素,而上下不会变.
如果你的视图是 .Xib 文件,则你的 margins 属性会在你的上下左右全部添加8个像素.
(PS: 苹果可视化推荐的间距就是8像素,大家可以注意一下)
了解了基础属性,下面就正式进入代码阶段,来个小项目练练手.
为了方便第一次使用的同学阅读,每个视图的约束都尽量设置全,方便理解.
//
将三个视图添加进父视图
UIView *greenView = [[ UIView alloc ] init ];
greenView. backgroundColor = [ UIColor redColor ];
[ self . view addSubview :greenView];
UIView *redView = [[ UIView alloc ] init ];
redView. backgroundColor = [ UIColor blueColor ];
[ self . view addSubview :redView];
UIView *blueView = [[ UIView alloc ] init ];
blueView. backgroundColor = [ UIColor greenColor ];
[ self . view addSubview :blueView];
int padding = 10 ;
// 添加约束
[greenView mas_makeConstraints :^( MASConstraintMaker *make) {
//Masonry 中添加属性基本都是 make 开头
//equalTo : 表示 添加属性 和 某个视图或者位置 相等
//offset : 表示 对前面 self.view.mas_left 这个位置偏移多少
UIView *greenView = [[ UIView alloc ] init ];
greenView. backgroundColor = [ UIColor redColor ];
[ self . view addSubview :greenView];
UIView *redView = [[ UIView alloc ] init ];
redView. backgroundColor = [ UIColor blueColor ];
[ self . view addSubview :redView];
UIView *blueView = [[ UIView alloc ] init ];
blueView. backgroundColor = [ UIColor greenColor ];
[ self . view addSubview :blueView];
int padding = 10 ;
// 添加约束
[greenView mas_makeConstraints :^( MASConstraintMaker *make) {
//Masonry 中添加属性基本都是 make 开头
//equalTo : 表示 添加属性 和 某个视图或者位置 相等
//offset : 表示 对前面 self.view.mas_left 这个位置偏移多少
//multipliedBy :表示这个视图占之前的视图大小的几分之几,0.5就是占一半
//center :
表示
这个视图和之前的视图中心点的位置
make.
top
.
equalTo
(
self
.
view
.
mas_top
) .
offset
(
0
);
make. left . equalTo ( self . view . mas_left ) . offset ( 0 );
make. width . equalTo ( self . view . mas_width ) . multipliedBy ( 0.5 );
make. height . equalTo ( self . view . mas_height ). multipliedBy ( 0.5 );
}];
[redView mas_makeConstraints :^( MASConstraintMaker *make) {
make. top . equalTo (greenView. mas_top );
make. left . equalTo (greenView. mas_right ). offset (padding);
// 当我们有多个属性和某个视图是完全一样的时候 , 我们可以使用 and 或者 with 关键词进行连接
make. height . and . width . equalTo (greenView);
}];
[blueView mas_makeConstraints :^( MASConstraintMaker *make) {
make. top . equalTo (greenView. mas_bottom ). offset (padding);
make. bottom . equalTo ( self . view ). offset (-padding);
make. left . equalTo ( self . view . mas_left ) . offset ( 0 );
make. width . equalTo ( self . view . mas_width ) . multipliedBy ( 0.5 );
make. height . equalTo ( self . view . mas_height ). multipliedBy ( 0.5 );
}];
[redView mas_makeConstraints :^( MASConstraintMaker *make) {
make. top . equalTo (greenView. mas_top );
make. left . equalTo (greenView. mas_right ). offset (padding);
// 当我们有多个属性和某个视图是完全一样的时候 , 我们可以使用 and 或者 with 关键词进行连接
make. height . and . width . equalTo (greenView);
}];
[blueView mas_makeConstraints :^( MASConstraintMaker *make) {
make. top . equalTo (greenView. mas_bottom ). offset (padding);
make. bottom . equalTo ( self . view ). offset (-padding);
make.left .equalTo(self.view).offset(padding);
make.
right
.
equalTo
(
self
.
view
).
offset
(-padding);
//
这里需要注意
,
我们添加约束还可以使用
mas_equalTo
//mas_equalTo : 后面的约束条件是数值或者结构体等类型 , 其本质就是 对其参数进行了一个 BOX 操作 ( 装箱 )
// 一般将数值类型的约束用 mas_equalTo ,而相对于某个控件,或者某个控件的某个约束,使用 equalTo
/*
下面附上官方原文
Instead of using NSNumber, you can use primitives and structs to build your constraints.
By default, macros which support autoboxing are prefixed with mas_.
Unprefixed versions are available by defining MAS_SHORTHAND_GLOBALS before importing Masonry.
//mas_equalTo : 后面的约束条件是数值或者结构体等类型 , 其本质就是 对其参数进行了一个 BOX 操作 ( 装箱 )
// 一般将数值类型的约束用 mas_equalTo ,而相对于某个控件,或者某个控件的某个约束,使用 equalTo
/*
下面附上官方原文
Instead of using NSNumber, you can use primitives and structs to build your constraints.
By default, macros which support autoboxing are prefixed with mas_.
Unprefixed versions are available by defining MAS_SHORTHAND_GLOBALS before importing Masonry.
*/
}];
当键盘挡住输入框时,输入框自动向上弹到键盘上方。
这里需要使用到Masonry的另外一个方法mas_updateConstraints。这个方法用于更新控件约束。
具体的实现方式可以下载Demo来看,这里只贴出键盘弹出时的处理代码:
- (
void
)keyboardWillChangeFrameNotification:(
NSNotification
*)notification {
// 获取键盘基本信息(动画时长与键盘高度)
NSDictionary
*userInfo = [notification userInfo];
CGRect
rect = [userInfo[
UIKeyboardFrameBeginUserInfoKey
]
CGRectValue
];
CGFloat
keyboardHeight =
CGRectGetHeight
(rect);
CGFloat
keyboardDuration = [userInfo[
UIKeyboardAnimationDurationUserInfoKey
] doubleValue];
// 修改下边距约束
[_textField mas_updateConstraints:^(MASConstraintMaker *make) {
make
.bottom
.mas_equalTo
(-keyboardHeight);
}
];
// 更新约束
[
UIView
animateWithDuration:keyboardDuration animations:^{
[
self
.view
layoutIfNeeded];
}];
}
更多精彩文章,尽在我的公众号.