AutoLayout介绍
AutoLayout的功能要比AutoResizing强大的多。
当对一个UIView对象使用了AutoLayout布局后,意味着放弃了通过对象的frame进行修改视图的位置、尺寸。
AutoLayout使约束条件,通过自动布局引擎,计算view对象的frame。
可以认为在AutoLayout中view对象的frame是一个只读的属性。
约束的核心公式:
view1.attr1 = (view2.attr2 * multiplier) + constraint
其中obj2可以是nil
除了=关系外,还可以是>= <=的关系
代码适配
添加约束的步骤:
1)禁止被适配view的AutoResizing功能
- (BOOL)translatesAutoresizingMaskIntoConstraints
- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag
2)创建约束对象NSLayoutConstraint
+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c
参数即约束的核心公式
NSLayoutRelation枚举:
enum {
NSLayoutRelationLessThanOrEqual = -1,
NSLayoutRelationEqual = 0,
NSLayoutRelationGreaterThanOrEqual = 1,
};
typedef NSInteger NSLayoutRelation;
NSLayoutAttribute枚举:
typedef enum: NSInteger {
NSLayoutAttributeLeft = 1,
NSLayoutAttributeRight,
NSLayoutAttributeTop,
NSLayoutAttributeBottom,
NSLayoutAttributeLeading,
NSLayoutAttributeTrailing,
NSLayoutAttributeWidth,
NSLayoutAttributeHeight,
NSLayoutAttributeCenterX,
NSLayoutAttributeCenterY,
NSLayoutAttributeBaseline,
NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline,
NSLayoutAttributeFirstBaseline,
NSLayoutAttributeLeftMargin,
NSLayoutAttributeRightMargin,
NSLayoutAttributeTopMargin,
NSLayoutAttributeBottomMargin,
NSLayoutAttributeLeadingMargin,
NSLayoutAttributeTrailingMargin,
NSLayoutAttributeCenterXWithinMargins,
NSLayoutAttributeCenterYWithinMargins,
NSLayoutAttributeNotAnAttribute = 0} NSLayoutAttribute;
3)在UIView对象上添加约束对象
- (void)addConstraint:(NSLayoutConstraint *)constraint
- (void)addConstraints:(NSArray *)constraints
将约束添加到哪个view对象上应按照以下规则:
对于同级view之间的约束关系,添加到它们的父控件上
对于不同级view之间的约束关系,添加到最近的共同父控件上
对于有层级关系的两个view之间约束关系,添加到层次较高的的空间上
注意:约束不能重复添加,不能缺少必要的约束
添加约束的过程中非常容易出现无法计算出frame的情况
UIView的其他操作约束的方法:
- (NSArray *)constraints
- (void)removeConstraint:(NSLayoutConstraint *)constraint
- (void)removeConstraints:(NSArray *)constraints
AutoLayout的补充
AutoLayout的动画:
代码中如果修改了约束的数值,则执行下面的代码,就能产生相应的动画效果。
[UIView animateWithDuration:1.0 animations:^{
[view layoutIfNeeded];
}];
哪个view中的约束变化了,哪个view对象调用layoutIfNeed方法
约束的变化应在动画之前完成。
UILabel、UIButton这类显示文字的控件使用AutoLayout的好处:
使用了恰当的约束,能够使其尺寸自动匹配。
如设置了UILabel对象的上、左、右的规定边距,则UILabel的尺寸会根据文字自动适应。
约束的VFL方式
Visual Format Language,可视化格式语言,是苹果公司为了简化AutoLayout的编码而推出的抽象语言。
其实不能称之为“语言”,可以认为这仅仅是一种“语法”,其目的是减少代码使用AutoLayout的编程量
但实际减少的程度有限,有些约束的功能使用VFL也无法完成,但在实现一些简单约束时非常有效。
NSLayoutConstraint的另一个创建方法:
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary*)views
format参数:VFL语句
views参数:VFL中出现的对象“键值对”
metrics:占位符
返回一组约束对象
VFL语句示意:
如:
canelButton宽72,acceptButton宽50,它们之间间距12
H:[cancelButton(72)]-12-[acceptButton(50)]
wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)
H:[wideView(>=60@700)]
竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox
V:[redBox]-[yellowBox(==redBox)]
水平方向上,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|” 表示superview的边缘)
H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
ZXPAutoLayout
号称最轻巧的自动布局,简化了NSLayoutConstraint的繁琐,采用新颖的链式语法,可扩展性强,维护成为低。
使用 zxp_addAutoLayout添加布局, 如:
[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
}];
单个view的布局关系:
在superview中的内边距:
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^topSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^leftSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^bottomSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^rightSpace)(CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^edgeInsets)(UIEdgeInsets insets);
如:
[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
//layout.topSpace(20);
//layout.bottomSpace(30);
//layout.leftSpace(40);
//layout.rightSpace(50);
layout.edgeInsets(UIEdgeInsetsMake(20, 30, 40, 50));
}];
居中操作:
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^xCenterByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^yCenterByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^centerByView)(UIView *view,CGFloat value);
参数view应为superview
宽高操作:
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^widthValue)(CGFloat value);
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^heightValue)(CGFloat value);
如:
[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
layout.xCenterByView(self.view, 0);
layout.yCenterByView(self.view, -100);
layout.widthValue(100);
layout.heightValue(100);
}];
两个view的布局关系:
//与另一个view的内边距相等
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^edgeEqualTo)(UIView *view);
//当前的top距离view为value点坐标距离
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^topSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^leftSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^bottomSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^rightSpaceByView)(UIView *view,CGFloat value);
//当前top内边距值与view的相等
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^topSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^leftSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^bottomSpaceByView)(UIView *view,CGFloat value);
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^rightSpaceByView)(UIView *view,CGFloat value);
//与view等宽
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^widthEqualTo)(UIView *view,CGFloat value);
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^heightEqualTo)(UIView *view, CGFloat value);
如:
[self.redView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
layout.xCenterByView(self.view, 0);
layout.yCenterByView(self.view, -100);
layout.widthValue(100);
layout.heightValue(100);
}];
[self.blueView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
layout.topSpaceByView(self.redView, 100);
layout.heightEqualTo(self.redView, 0);
layout.widthEqualTo(self.redView, 0);
layout.leftSpaceEqualTo(self.redView, 0);
}];
自适应操作:(对UILabel有效)
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoHeight)();
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoHeightByMin)(CGFloat value);
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoWidth)();
@property (copy,nonatomic,readonly) ZXPAutoLayoutMaker *(^autoWidthByMin)(CGFloat value);
其他操作:
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^priority)(UILayoutPriority priority); //优先级
@property (copy, nonatomic, readonly) ZXPAutoLayoutMaker *(^multiplier)(CGFloat multiplier); //约束的倍数
如:
[self.blueView zxp_addConstraints:^(ZXPAutoLayoutMaker *layout) {
layout.topSpaceByView(self.redView, 100);
layout.heightEqualTo(self.redView, 0).multiplier(0.5);
layout.widthEqualTo(self.redView, 0);
layout.leftSpaceEqualTo(self.redView, 0);
}];
转载于:https://blog.51cto.com/annmeng/1745967