iOS自动布局之VisualFormat

Posted wangjunling888

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS自动布局之VisualFormat相关的知识,希望对你有一定的参考价值。

VFL是苹果推出的用来AutoLayout布局的一门比较形象的语言, 本身为字符串,虽然用起来比较麻烦, 但是相比直接使用苹果的另一个套布局方案要少写一些代码, 那么问题来了, github上那么多自动布局的框架, 简单又好用, 为什么要用这么复杂的代码去布局呢, 之前我也这么想, 直到有一天自己想封装一个框架的的时候才发现, 不能处处依赖别人的框架去封装, 因为这样的话, 你封装的框架几乎没法用. 举个例子, 假设你的框架用了AFN的2.0版本, 那么对于使用框架的人来说, 他们项目中如果使用了AFN3.0, 那么肯定出出现一大堆兼容问题, 因此对于自己的封装的框架, 要以原生为主. 废话不多说 下面总结一下我半天的的学习成果: VFL布局

下面是VFL使用的一个核心方法

+ (NSArray<__kindof NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format 
  options:(NSLayoutFormatOptions)opts 
  metrics:(nullable NSDictionary<NSString *,id> *)metrics 
    views:(NSDictionary<NSString *, id> *)views;

该方法一共有四个参数, 接下来将一一讲解四个参数的含义及其使用:

  1. format参数: 这个是具体布局的字符串,形如 @”V:|-10-[view1(50.0)]-20-[view2(50.0)]” 稍后再讲解此字符串的意思;
  2. option参数: 这个参数是一个可复选的参数, 主要用来布局view的对齐方式;
  3. metrics参数: 这个参数是替换VFL字符串中的变量用的, 如果这么写: @@”topMargin”:@10 则第一条中的布局可以替换成下面的写法: @”V:|-10-[view1(50.0)]-20-[view2(50.0)]” 其实就是替换字符串中的变量使用;
  4. views参数: 这个参数是用来存储本条VFL语句中所有用到的View, 可以直接创建字典 @@”view1”:view1, @”view2”:view2 对于这个参数苹果有一个特定的宏, NSDictionaryOfVariableBindings() 因此也可以这样写 NSDictionaryOfVariableBindings(view1, view2) ;

该方法返回的是一个装有约束的数组集合;可以直接添加到设定约束view的父view上;

如果你对上面的解释不太理解下面用代码具体举个列子,相信你立马回恍然大悟

- (void)viewDidLoad 
    [super viewDidLoad];
    [self testConstraint];


- (void)testConstraint //测试布局

    UIView *supView1 = [[UIView alloc] init];
    supView1.backgroundColor =  [UIColor blueColor];

    UIView *supView2 = [[UIView alloc] init];
    supView2.backgroundColor =  [UIColor blueColor];

    [self.view addSubview:supView1];
    [self.view addSubview:supView2];


    //由于AutoLayout布局和Autoresizing布局是冲突的,因此要使用AutoLayout必须要关闭Autoresizing
    self.view.translatesAutoresizingMaskIntoConstraints = NO;
    supView2.translatesAutoresizingMaskIntoConstraints = NO;
    supView1.translatesAutoresizingMaskIntoConstraints = NO;



    //此语句的意思是 垂直方向: supView1距离父view的距离为 topMargin,
    //supView1的垂直方向的宽度为50.0, supView2距离supView1为20, 并且高度也为50.0;
    NSString *top = @"V:|-topMargin-[supView1(50.0)]-20-[supView2(50.0)]";
    //解释方法同上
    NSString *left = @"H:|-10-[supView1(50.0)]";
    NSString *v2T = @"[supView2(60.0)]";


    //此处需要对topMargin参数进行解释, 其实就是给topMargin赋值;
    NSArray *s1T = [NSLayoutConstraint constraintsWithVisualFormat:top options:NSLayoutFormatAlignAllRight metrics:@@"topMargin":@100 views:NSDictionaryOfVariableBindings(supView1, supView2)];

    NSArray *s1L = [NSLayoutConstraint constraintsWithVisualFormat:left options:0 metrics:nil views:NSDictionaryOfVariableBindings(supView1)];
    NSArray *v2Tc = [NSLayoutConstraint constraintsWithVisualFormat:v2T options:0 metrics:nil views:NSDictionaryOfVariableBindings(supView2)];

    //一般需要把约束添加到父view上
    [self.view addConstraints:v2Tc];
    [self.view addConstraints:s1T];
    [self.view addConstraints:s1L];


效果如下图:

上面的例子只是简单的使用了一下VFL语句, 其实还有更多的东西, 需要自己去慢慢的理解体会多使用, 熟练了就好了, 对于其他的VFL语句的用法请参考附录里面的详细使用

附录

  1. 符号含义

    |:   表示父视图
    -:  表示距离
    V:  表示垂直
    H:  表示水平
    >=: 表示视图间距、宽度和高度必须大于或等于某个值
       <= :表示视图间距、宽度和高度必须小宇或等于某个值
       == :表示视图间距、宽度或者高度必须等于某个值
    @:  优先级 最大为  1000
  2. 一般用法:

    |-[view]-|:                          视图处在父视图的左右边缘内
    |-[view]  :                              视图处在父视图的左边缘
    |[view]   :                              视图和父视图左边对齐
    V:[view(100.)]  :                        设置视图的高度 
    H:[view(100.)]  :                        设置视图的宽度
    |-30.0-[view]-30.0-|:                表示离父视图 左右间距  30
    |-[view(view1)]-[view1]-| :              View和view1视图宽度一样,并且在父视图内
    V:|-padding-[imageView]->=0-[button]-padding| : 表示离父视图的距离为Padding,这两个视图间距必须大于或等于0并且距离底部父视图为padding。此时必须对 metrics参数赋值eg.  metrics:@@"topMargin":@100;
    
    [wideView(>=60@700)]  :视图的宽度为至少为60 优先级为700
    
    最后要注意, H可以忽略, 默认为水平布局 , V必须要写!!!

好了码了半天终于大功告成, 希望此博客对你有帮助, 记得点赞哦~

以上是关于iOS自动布局之VisualFormat的主要内容,如果未能解决你的问题,请参考以下文章

如何使用ios中的自动布局将三个按钮并排放置在中心并留有间距?

iPad纵向和横向的自动布局iOS8

iOS 自动布局 >> 视图没有改变它的大小

iOS - iPad 布局顶部/底部间距似乎没有按照我说的做

ios将3个视图放置在另一个具有自动布局的视图中

自动布局等间距和加权间距