iOS界面布局之三——纯代码的autoLayout及布局动画
一、引言
关于界面布局,apple的策略已经趋于成熟,autolayout的优势在开发中也已经展现的淋漓尽致。除了使用storyBoard进行布局约束的拖拽,有时我们也需要在代码中进行autolayout的布局设置,Masonry库可以方便的创建约束属性,实际上,我们也没有必要再使用系统原生的代码来创建和设置约束,这篇博客只作为使用的方法备忘。前几篇布局介绍的链接如下:
使用autoresizing进行界面布局:http://my.oschina.net/u/2340880/blog/423357
初识autolayout布局模型:http://my.oschina.net/u/2340880/blog/423500
二、了解一个类
用代码来做视图间的相关约束,那么就一定要将“约束”也进行对象化,在iOS6之后,引入了autolayout这个概念,相应的也增加了NSLayoutConstraint这个对象,这个对象就是专门用来进行约束布局的设置对象。通过这个对象,我们可以设置类似视图对象之间的间距,约束的宽高,比例等属性。创建NSLayoutConstraint对象的方法有两种,下面我们分别介绍:
1、使用Objective-C风格的方法创建约束对象
所谓Objective-C风格的方法,就是通过原生枚举和一些属性设置来创建NSLayoutConstraint对象。使用NSLayoutConstraint类的如下方法:
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
先来介绍下方法中的参数都是什么意义,我们应该怎么用他们:
view1:要添加约束的视图对象。
attr1:要约束的对象属性,这个就是一些枚举,如下:
typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
NSLayoutAttributeLeft = 1,//左
NSLayoutAttributeRight,//右
NSLayoutAttributeTop,//上
NSLayoutAttributeBottom,//下
NSLayoutAttributeLeading,//起始边,类似左,只在某些从右向左排列的语言中和NSLayoutAttributeLeft有大区别
NSLayoutAttributeTrailing,//结束边
NSLayoutAttributeWidth,//宽度
NSLayoutAttributeHeight,//高度
NSLayoutAttributeCenterX,//x中心
NSLayoutAttributeCenterY,//y中心
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
};
relation:约束的选项,对应<=,==,>=这些,枚举如下:
typedef NS_ENUM(NSInteger, NSLayoutRelation) {
NSLayoutRelationLessThanOrEqual = -1,//<=
NSLayoutRelationEqual = 0,//==
NSLayoutRelationGreaterThanOrEqual = 1,//>=
};
view2:与之对应添加约束的视图对象,例如,如过我要设置view1的上边距离父视图的上边一定间距,这个view2就是view1的父视图,如果我要设置view1与另一个视图一定距离,这个view2就是另一个视图。
attr2:view2的要约束的属性,和attr1含义一样。
multiplie:约束的比例,比如view1的宽是view2的宽的两倍,这个multiplie就是2.
C:这是具体的约束值
对于这些属性,文档上有这样的解释:view1.attr1 = view2.attr2 * multiplier + constant
例如,我们创建一个label,将它的宽高固定为100*100,位置放在屏幕的中央,我们可以使用如下的约束代码:
UILabel * label = [[UILabel alloc]init];
label.numberOfLines = 0;
//使用代码布局 需要将这个属性设置为NO
label.translatesAutoresizingMaskIntoConstraints = NO;
label.backgroundColor = [UIColor redColor];
//创建x居中的约束
NSLayoutConstraint * constraintx = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
//创建y居中的约束
NSLayoutConstraint * constrainty = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
//创建宽度约束
NSLayoutConstraint * constraintw = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100];
//创建高度约束
NSLayoutConstraint * constrainth = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:100];
//添加约束之前,必须将视图加在父视图上
[self.view addSubview:label];
[self.view addConstraints:@[constraintx,constrainty,constrainth,constraintw]];
效果如下:
可以发现,一个如此简单的约束方式,我们用这样的代码要写这么一大坨,麻烦而且不直观。于是,apple又提供给我们下面一种方式。
2.使用ASCLL字符创造艺术般的格式化字符串约束
看到这个小标题是不是眼前一亮,这个标题不是我凭空想象出来的,apple的文档上就是这么写的。十分可爱,对吧。相对于NSLayoutConstraint中的创建方法如下:
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;