iOS学习之自动布局-Autolayout

Autolayout:

最重要的两个概念

  • 约束:对控件位置和大小的限定条件
  • 参照:对控件设置的约束是相对于哪一个视图而言的

自动布局的核心计算公式

obj1.property1 =(obj2.property2 * multiplier)+ constant value

解释:obj1的property1属性等于obj2的property2属性乘以multiplier(系数)再加constant(常量);

约束的优先级:

约束的priority属性表示约束的优先级,取值区间为[0,1000],默认为1000。priority值越大,表示优先级越高,会优先执行。优先级低的约束只有在优先级较高的约束失效后才会执行。

警告和错误:

在使用storyboard和xib设置约束时,约束有可能会变成黄色或者红色。当发生这样的情况时,就说明设置的约束有问题。

  • 如果约束是黄色的,这只是一个警告,代表控件的frame和设置的约束不相符,更新frame或者更新约束就可以解决。
  • 如果约束是红色的,这就代表错误,约束设置不完全或者某两个约束有冲突,只有约束设置完整并且没有冲突,红色错误提示才会消失。

添加约束的3条规则:

  • 对于两个同层级View之间的约束关系,应该添加到它们的父View之上。
  • 对于两个不同层级View之间的约束关系,应该添加到它们最近的共同父View上。
  • 对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上

代码实现Autolayout:

代码实现Autolayout需要注意:

  • 必须先禁止autoresizing功能,设置View的下面属性为NO
    view.translatesAutoresizingMaskIntoConstraints = NO;
  • 添加约束之前,一定要保证相关控件都已经添加到各自的父控件上了
  • 不用再给View设置frame

利用NSLayoutConstraint类创建具体的约束对象

添加约束到相应的View上:

- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray *)constraints;

NSLayoutConstraint:

一个NSLayoutConstraint对象就代表一个约束,可以通过修改NSLayoutConstraint对象的属性来修改约束。

创建约束对象常用的方法:

/**
 *  添加一个约束,其实就是根据公式来计算约束
 *  obj1.property1 =(obj2.property2 * multiplier)+ constant value
 *  @param view1      需要添加约束的View
 *  @param attr1      需要添加的约束(左边、右边、长宽还是。。。)
 *  @param relation   约束关系(大于、等于还是小于)
 *  @param view2      参照View(约束是相对于哪个View而言)
 *  @param attr2      参照View的哪一个参数(左边、右边、长宽还是。。。)
 *  @param multiplier 系数
 *  @param c          常量值
 *
 *  @return 返回一个创建好的约束
 */

+ (instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;

示例:

UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];

//关闭Autoresizing
blueView.translatesAutoresizingMaskIntoConstraints = NO;

//创建左边约束
NSLayoutConstraint *leftLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
[self.view addConstraint:leftLc];

//创建右边约束
NSLayoutConstraint *rightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
[self.view addConstraint:rightLc];

//创建底部约束
NSLayoutConstraint *bottomLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20];
[self.view addConstraint:bottomLc];

//创建高度约束
NSLayoutConstraint *heightLc = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:50];
[blueView addConstraint: heightLc];

效果图:

使用VFL语句添加约束:

使用VFL来创建约束数组:

/**
*  使用VFL语句来创建约束数组
*
*  @param format  VFL语句
*  @param opts    约束类型
*  @param metrics VFL语句中用到的具体数值
*  @param views   VFL语句中用到的控件
*
*  @return 返回创建好的约束数组
*/
+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views;

VFN语句示例:

H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton宽72,acceptButton宽50,它们之间间距12

H:[wideView(>[email protected])]
wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)

V:[redBox][yellowBox(==redBox)]
竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox

H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|” 表示superview的边缘)

VFN代码示例:

    // 创建蓝色View
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];

    // 创建红色View
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];

    // VFL创建约束
    // 水平方向
    NSString *VFL_H = @"H:|-space-[blueView]-space-[redView(==blueView)]-space-|";
    NSDictionary *metrics = @{
                              @"space" : @30,
                              };
    //    NSDictionary *views = @{
    //                            @"blueView" : blueView,
    //                            @"redView" : redView
    //                            };
    NSDictionary *views = NSDictionaryOfVariableBindings(blueView,redView);

    NSArray *arrayH = [NSLayoutConstraint constraintsWithVisualFormat:VFL_H options:NSLayoutFormatAlignAllTop metrics:metrics views:views];
    [self.view addConstraints:arrayH];

    // 垂直方向
    NSString *VFL_V = @"V:[blueView(50)]-space-|";
    NSArray *arrayV = [NSLayoutConstraint constraintsWithVisualFormat:VFL_V options:kNilOptions metrics:metrics views:views];
    [self.view addConstraints:arrayV];

    // 添加红色View的约束
    // 添加高度约束
    NSLayoutConstraint *redV_height = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
    [self.view addConstraint:redV_height];

效果图:

什么是VFL语言

VFL(Visual Format Language),“可视化格式语言”。

VFL是苹果公司为了简化autolayout的编码而推出的抽象语言。

语法说明

H:[cancelButton(72)]-12-[acceptButton(50)]
cancelButton宽72,acceptButton宽50,它们之间间距12

H:[wideView(>[email protected])]
wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束条件越先被满足)

V:[redBox][yellowBox(==redBox)]
垂直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox

H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上,Find距离父view左边缘间隔10,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边边缘的间距都是默认宽度。(竖线“|”表示superview的边缘)。

使用方法

使用VFL来创建约束数组
+(NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;

format:VFL语句
opts:约束类型
metrics:VFL语句中用到的具体数值
views:VFL语句中用到的控件

创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义
NSDictionaryOfVariableBindings(...)

实例展示

效果图如下:

实现代码

-(void)horizontalLayout{
    //1.添加两个控件
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];

    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];

    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];

    //2.添加约束
    //2.1水平方向的约束
    NSString *hVFL = @"H:|-30-[blueView]-30-[redView(==blueView)]-30-|";
    NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hVFL options:NSLayoutFormatAlignAllBottom | NSLayoutFormatAlignAllTop metrics:nil views:@{@"blueView":blueView, @"redView":redView}];
    [self.view addConstraints:hCons];

    //2.2垂直方向的约束
    NSString *vVFL = @"V:[blueView(50)]-30-|";
    NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vVFL options:0 metrics:nil views:@{@"blueView":blueView}];
    [self.view addConstraints:vCons];
}

-(void)verticalLayout{
    //1.添加两个控件
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];

    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];

    //2.添加约束
    //2.1水平方向的约束
    NSString *hVFL = @"H:|-30-[blueView]-30-|";
    NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:hVFL options:0 metrics:nil views:@{@"blueView":blueView}];
    [self.view addConstraints:hCons];

    //2.2垂直方向的约束
    NSString *vVFL = @"V:|-30-[blueView(50)]-30-[redView(==blueView)]";
    NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:vVFL options:NSLayoutFormatAlignAllRight metrics:nil views:@{@"blueView":blueView, @"redView":redView}];
    [self.view addConstraints:vCons];
    NSLayoutConstraint *redLeftCon = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
    [self.view addConstraint:redLeftCon];
}

小结

最后对格式的字符串作一个总结介绍:

功能 表达式
水平方向 H:
垂直方向 V:
Views [view]
SuperView 竖线符号
关系 >=,==,<=
空间,间隙 -
优先级 @value

 

 

 

Masonry的使用:

Masonry是目前最流行的Autolayout第三方框架,让你可以用简单的代码来编写Autolayout,省去了苹果官方繁复的Autolayout代码,大大提升了开发效率。

mas_equalToequalTo

默认情况下mas_equalTo有自动包装功能,比如自动将20包装为@20equalTo没有自动包装功能。

如果添加了下面的宏,那么mas_equalToequalTo就没有区别:

#define MAS_SHORTHAND_GLOBALS
// 注意:这个宏一定要添加到#import "Masonry.h"前面

mas_widthwidth:

默认情况下
widthmake对象的一个属性,用来添加宽度约束用的,表示对宽度进行约束。mas_width是一个属性值,用来当做equalTo的参数,表示某个控件的宽度属性。

如果添加了下面的宏,mas_width也可以写成width:
#define MAS_SHORTHAND

mas_heightmas_centerX以此类推。

下面用Masonry框架实现一下上面VFL语句的示例,对比一下就会发现有了Masonry框架以后自动布局变得多么容易:

//创建蓝色控件
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];

//创建红色控件
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];

// 添加blueView的约束
[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(redView.width).offset(0);
    make.height.equalTo(redView.height).offset(0);
    make.height.equalTo(100);
    make.left.equalTo(blueView.superview.left).offset(20);
    make.bottom.equalTo(blueView.superview.bottom).offset(-20);
    make.right.equalTo(redView.left).offset(-20);
}];

// 添加redView的约束
[redView makeConstraints:^(MASConstraintMaker *make) {
    make.bottom.equalTo(redView.superview.bottom).offset(-20);
    make.right.equalTo(redView.superview.right).offset(-20);
}];

Masonry框架提供了很多示例程序,感兴趣的可以打开上面GitHub的链接下载下来仔细研究,这里就不多写了。
GitHub链接为:https://github.com/SnapKit/Masonry

约束动画:

在执行动画时记得调用以下方法:

//在修改了约束之后,只要执行下面代码,约束就能做出动画效果
[UIView animateWithDuration:0.5 animations:^{
      [self.view layoutIfNeeded];
  }];

使用Autolayout实现UILabel内容包裹:

  • 1、设置UILabel的位置约束
  • 2、设置label.numberOfLines = 0;,使label能够自动换行来计算高度
  • 3、代码创建约束时,应设置label的最大宽度preferredMaxLayoutWidth
时间: 2024-08-24 08:12:22

iOS学习之自动布局-Autolayout的相关文章

IOS学习之 记录autolayout后的frame的处理

界面使用自动布局后,在代码中的viewDidLoad方法中获取到UIView的frame的值不是实时的,依旧是相对于600 * 600 的界面的frame.需要在viewWillAppear 或者viewDidAppear的方法中获取UIView的frame,才是正确的,因为此时的view才全部初始化了. 记录一个CAGradientLayer的frame的问题,它的frame也是相对于父视图(就是需要insertSublayer的那个view)的位置的,所以oragin的位置时相对于view的

iOS学习之Storyboard中的UIScrollView使用自动布局

在使用storyboard和xib时,我们经常要用到ScrollView,还有自动布局AutoLayout,但是ScrollView和AutoLayout 结合使用,相对来说有点复杂.根据实践,我说一下我的理解,在故事板或xib中,ScrollView是根据其下面的一个View的大小来确定ContentSize的大小. 看一下效果 1. 创建一个项目,拖拽一个ScrollView到故事板中,如下图 2. 选中ScrollView,添加约束. 3. 拖拽一个View到ScrollView上, 然后

iOS: 学习笔记, 用代码驱动自动布局实例

iOS自动布局是设置iOS界面的利器. 本实例展示了如何使用自动布局语言设置水平布局, 垂直布局 1. 创建空白iOS项目 2. 添加一个控制器类, 修改YYAppDelegate.m文件 #import "YYAppDelegate.h" #import "YYViewController.h" @implementation YYAppDelegate - (BOOL)application:(UIApplication *)application didFin

iOS: 学习笔记, 用代码驱动自动布局实例(swift)

iOS自动布局是设置iOS界面的利器.本实例展示了如何使用自动布局语言设置水平布局, 垂直布局1. 创建空白iOS项目(swift)2. 添加一个控制器类, 修改YYAppDelegate.swift文件 @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFi

iOS学习资源收集

https://github.com/Tim9Liu9/TimLiu-iOS 自己总结的iOS.mac开源项目及库,持续更新.... github排名 https://github.com/trending,github搜索:https://github.com/search 目录 UI 下拉刷新 模糊效果 AutoLayout 富文本 图表 表相关与Tabbar 隐藏与显示 HUD与Toast 对话框 其他UI 动画 侧滑与右滑返回手势 gif动画 其他动画 网络相关 网络连接 图像获取 网络

自动布局autoLayout解决不同屏幕

这篇不是autolayout教程,只是autolayout动员文章和经验之谈,在本文第五节友情链接和推荐中,我将附上足够大家熟练使用autolayout的教程.这篇文章两个月前就想写下来,但因为一直工作较多,没有时间来完成.今天终于狠下心,丢下代码不写,来完成他吧! 一.别和我提Autolayout,我想死!! 从iOS6/xcode4开始,苹果开始提供了autolayout——一种对不同屏幕尺寸有更好兼容的自动布局机制,但我相信大多数人在刚接触autolayout时,一定和我一样,几乎快被其折

iOS学习资源搜集

最快速的学习方法是站在别人的肩上,当有人给你垫脚,那就必须往远处看.以下是遇到的一些好的学习资源. AutoLayout / SizeClass 开始iOS 7中自动布局教程(一) 开始iOS 7中自动布局教程(二) Auto Layout 使用心得(一)—— 初体验 Auto Layout 使用心得(二)—— 实现三等分 xcode6中自动布局autolayout和sizeclass的使用 xcode6下使用autolayout+sizeclass实践 ios8新特性屏幕适配之sizeclas

(翻译)开始iOS 7中自动布局教程(二)

这篇教程的前半部分被翻译出来很久了,我也是通过这个教程学会的IOS自动布局.但是后半部分(即本篇)一直未有翻译,正好最近跳坑翻译,就寻来这篇教程,进行翻译.前半部分已经转载至本博客,后半部分即本篇.学习IOS自动布局的朋友可以看看.自动布局很强大. 这篇教程绝对的最好的学习IOS自动布局的文章,没有之一 原文地址:Beginning Auto Layout Tutorial in iOS 7: Part 2 正文如下: 请注意: 团队成员Matthijs Hollemans (IOS学徒系列的作

iOS: 学习笔记, 添加一个带界面约束的控制器

1. 创建一个空iOS应用程序(Empty Application). 2. 添加加控制器类. 修改控制器类的viewDidLoad 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 //创建标题 5 UILabel *header = [[UILabel alloc] init]; 6 header.text = @"欢迎来到我的世界!"; 7 header.textAlignment = NSTextAlignmentCenter