Autoresizing:
苹果在iOS2中引入了Autoresizing技术用于屏幕适配, 其用于指定当父视图的bounds发生改变时如何自动调整子视图的布局
// 默认为YES
@property(nonatomic) BOOL autoresizesSubviews;
// 默认为UIViewAutoresizingNone
@property(nonatomic) UIViewAutoresizing autoresizingMask;
autoresizesSubviews属性用于标识当自身的bounds发生改变时是否自动调整子视图的布局;
autoresizingMask属性用于标识当父视图的bounds发生改变时如何自动调整自身的布局
autoresizingMask属性的取值为UIViewAutoresizing枚举, 可以采用位运算(按位或)同时设置多个值
UIViewAutoresizingNone = 0, 不执行任何调整
UIViewAutoresizingFlexibleLeftMargin = 1<< 0, 自动调整与父视图的左边距
UIViewAutoresizingFlexibleWidth = 1<< 1, 自动调整自身的宽度
UIViewAutoresizingFlexibleRightMargin = 1<< 2, 自动调整与父视图的右边距
UIViewAutoresizingFlexibleTopMargin = 1<< 3, 自动调整与父视图的上边距
UIViewAutoresizingFlexibleHeight = 1<< 4, 自动调整自身的高度
UIViewAutoresizingFlexibleBottomMargin = 1<< 5, 自动调整与父视图的下边距
CGFloat width = [[UIScreen mainScreen] bounds].size.width;
CGFloat height = [[UIScreen mainScreen] bounds].size.height;
UIView*redView = [[UIViewalloc]initWithFrame:CGRectMake(width-120, height-120,100,100)];//距离右下分别为20
redView.backgroundColor = [UIColor redColor];
redView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin; //当调整父视图时,redView的上部和左部会发生调整
[self.view addSubview:redView];
注意事项
1.必须设置 translatesAutoresizingMaskIntoConstraints为NO。
2.如果是viewControl则AutoLayout适配写在[- updateViewConstraints]中;如果是view则AutoLayout适配写在[- updateConstraints]中。
每个view都有一个只读的constraints数组对象,这个数组对象为NSArray<__kindof NSLayoutConstraint *>类型,NSLayoutConstraint的意义是代表着一条约束,NSLayoutAttribute的生成方法为:
+(instancetype) constraintWithItem: (id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullableid)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
[aview addConstraint:[NSLayoutConstraint constraintWithItem:bview attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:aview attribute:NSLayoutAttributeLeft multiplier:1.0 constant:10]];
计算关系为:bview.left = aview.left*1.0+10
我们需要学习的是NSLayoutAttribute和NSLayoutRelation;
priority(优先级)设置优先级的目的是当布局冲突时优先级高的生效,当优先级高的约束失效以后优先级低的就生效了;注意控件默认的优先级为1000,并且控件的优先级取值范围为[0 1000]
例子:一个UILabel的布局为
make.left.offset(10);
make.top.offset(50);
make.right.offset(0);
make.width.lessThanOrEqualTo(@200);
上面可以看出label的left、right约束和width.lessThanOrEqualTo冲突,可以设置距离right约束的优先级小于lessThanOrEqualTo即可:
make.right.offset(0).priority(900);
make.width.lessThanOrEqualTo(@200).priority(1000);
activateConstraints,deactivateConstraints可以修改是否使用或者废弃某个约束
NSLayoutAttribute:
NSLayoutAttributeLeading, NSLayoutAttributeTrailing,表示前后;这两个约束在中国和left、right一样,但是在一些阿拉伯国家相反
NSLayoutAttributeBaseline: 文本底标线,在大多数视图中等同于NSLayoutAttributeBottom; 在少数视图,如UILabel,是指字母的底部出现的位置;
NSLayoutAttributeLastBaseline: 相当于NSLayoutAttributeBaseline;
NSLayoutAttributeFirstBaseline: 文本上标线;
NSLayoutRelation:
NSLayoutRelationLessThanOrEqual = -1, 小于等于
NSLayoutRelationEqual =0, 等于
NSLayoutRelationGreaterThanOrEqual =1, 大于等于
Intrinsic Contenet Size:固有的内容尺寸
UILabel,UIImageView,UIButton等这些组件及某些包含它们的系统组件都有 Intrinsic Content Size 属性。
也就是说,遇到这些组件,你只需要为其指定位置即可。大小就使用Intrinsic Content Size就行了;通俗的讲,具有intrinsic content size的控件自己知道(可以计算)自己的大小。
由于内容可以动态变化那么就带来了一些布局冲突问题:
[self.orangeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(10);
make.top.offset(50);
}];
[self.yellowLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.offset(50);
make.right.offset(-10);
make.left.equalTo(self.orangeView.mas_right).offset(10);
}];
上面的例子由于label的大小都是由系统计算,当两个label的内容长度都超过屏幕尺寸的话就会造成一方被另一方压缩挤压,可能会把另一个label挤出屏幕;针对这个问题自动布局引入了另一个属性:
content Hugging/content Compression Resistance :不想变大约束/不想变小约束
添加以下代码:
[self.orangeLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[self.yellowLabel setContentCompressionResistancePriority: UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
上面的代码可以实现当orangeLabel和yellowLabel的内容大小冲突时,两者以yellowLabel的内容为主,yellowLabel拉伸,orangeLabel压缩,但是orangeLabel不会被挤出屏幕