AutoLayout  VFL可视化格式约束

一、VFL简介

iOS的自动布局约束主要有三种方式,

1.可视化界面中添加布局,比如在Storyboard xib。

2.代码添加当个约束

3.VFL格式约束

VFL添加约束的优点

1.可以一行代码添加多个约束和多个对象

2.动态性大

3.不依赖其他框架。

4.只需要直观的从垂直和水平方向考虑

现在在代码添加约束中有很多优秀的框架,它们的内部大都是用NSLayoutConstraint,在编写基础控件时,为了减少对其他库的依赖,最好使用原生的约束。

二、VFL语法

语法标记

标记示例

修正:上图中最后一句修改完,如果没有声明方向,则默认为水平H:

使用参数options

参与控件的 基础对齐方式
typedef NS_OPTIONS(NSUInteger, NSLayoutFormatOptions) {NSLayoutFormatAlignAllLeft = (1 << NSLayoutAttributeLeft),    //所有控件左对齐NSLayoutFormatAlignAllRight = (1 << NSLayoutAttributeRight),  //所有控件右对齐NSLayoutFormatAlignAllTop = (1 << NSLayoutAttributeTop),NSLayoutFormatAlignAllBottom = (1 << NSLayoutAttributeBottom),NSLayoutFormatAlignAllLeading = (1 << NSLayoutAttributeLeading),NSLayoutFormatAlignAllTrailing = (1 << NSLayoutAttributeTrailing),NSLayoutFormatAlignAllCenterX = (1 << NSLayoutAttributeCenterX),   //中心X对齐NSLayoutFormatAlignAllCenterY = (1 << NSLayoutAttributeCenterY),   //中心y对齐NSLayoutFormatAlignAllLastBaseline = (1 << NSLayoutAttributeLastBaseline),  // ????NSLayoutFormatAlignAllBaseline NS_SWIFT_UNAVAILABLE("Use 'alignAllLastBaseline' instead") = NSLayoutFormatAlignAllLastBaseline,  //基于底线对齐NSLayoutFormatAlignAllFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0) = (1 << NSLayoutAttributeFirstBaseline), //????NSLayoutFormatAlignmentMask = 0xFFFF,/* choose only one of these three*/NSLayoutFormatDirectionLeadingToTrailing = 0 << 16, // defaultNSLayoutFormatDirectionLeftToRight = 1 << 16,NSLayoutFormatDirectionRightToLeft = 2 << 16,  NSLayoutFormatDirectionMask = 0x3 << 16,  /* choose only one spacing format*/NSLayoutFormatSpacingEdgeToEdge API_AVAILABLE(ios(11.0),tvos(11.0)) = 0 << 19, // default/* Valid only for vertical layouts. Between views with text content the valuewill be used to determine the distance from the last baseline of the view aboveto the first baseline of the view below. For views without text content the topor bottom edge will be used in lieu of the baseline position.The default spacing "]-[" will be determined from the line heights of the fontsinvolved in views with text content, when present.*/NSLayoutFormatSpacingBaselineToBaseline API_AVAILABLE(ios(11.0),tvos(11.0)) = 1 << 19,NSLayoutFormatSpacingMask API_AVAILABLE(ios(11.0),tvos(11.0)) = 0x1 << 19,
};

三、使用实例

下面是VFL约束实例(Objective-C),扩展UITableView  为其添加空白占位图提示

1.取消自动转换约束

iOS系统会自动将frame位置转换为约束布局,所以需要手动取消,否则自己添加的约束无效。

    [imageView setTranslatesAutoresizingMaskIntoConstraints:NO];[label setTranslatesAutoresizingMaskIntoConstraints:NO];[placeholderView setTranslatesAutoresizingMaskIntoConstraints:NO];

2.绑定视图

方便在VisualFormat字符串  []  中使用,找到对应的控件。

 //  绑定视图  在 [] 中使用 这样才能找到相应的控件NSDictionary *views =  NSDictionaryOfVariableBindings(imageView,label); //注意这是一个宏定义方法 等效与 @{@"imageView":imageView ,@"label":label}【具有自定义别名功能】;

3.设置参数(度量)字典  动态变量绑定

 // 设置参数(度量)字典  变量数值动态化NSDictionary *metris = @{@"imageViewTop":@((self.bounds.size.height - image.size.height*2)/2),@"imageViewLeft":@((self.bounds.size.width - image.size.width*2)/2),@"imageViewHeight":@(image.size.height*2),@"imageViewWidth":@(image.size.width*2),};

4.通过VFL语法添加约束

// 通过VFL语法添加约束组//placeholderView水平方向约束NSArray<NSLayoutConstraint *> *placeholderHConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-imageViewLeft-[imageView(imageViewHeight)]" options:0 metrics:metris views:views];//placeholderView和label垂直方向约束NSArray *placeholderVConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-imageViewTop-[imageView(imageViewWidth)]-20-[label]" options:0 metrics:metris views:views];//label水平方向约束NSArray *labelHConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[label]-0-|" options:0 metrics:metris views:views];

5.将约束添加到父视图

// 将约束添加在父视图上[placeholderView addConstraints:labelHConstraints];[placeholderView addConstraints:placeholderHConstraints];[placeholderView addConstraints:placeholderVConstraints];

完整代码

#import "UITableView+LF.h"static NSInteger const placeholderViewTag = 18181818 ;@implementation UITableView (LF)
/*** 添加空白占位图* @param image 占位图* @param title 图片底部标题* @param block 配置label */
-  (void)addPlaceholderImage:(nullable UIImage *)image bottomTitle:(nullable NSString *)title block:(void (^)(UILabel *label)) block{UIView *placeholderView = [[UIView alloc] init];placeholderView.tag = placeholderViewTag;[self addSubview:placeholderView];UIImageView *imageView = [[UIImageView alloc] init];imageView.image = image;[placeholderView addSubview:imageView];UILabel *label = [UILabel new];label.text = title ;label.textAlignment = NSTextAlignmentCenter;label.numberOfLines = 1;label.font = [UIFont systemFontOfSize:14];label.textColor = [UIColor darkGrayColor];if (block) {block(label);}[placeholderView addSubview:label];//使用VFL约束// 取消自动转换约束[imageView setTranslatesAutoresizingMaskIntoConstraints:NO];[label setTranslatesAutoresizingMaskIntoConstraints:NO];[placeholderView setTranslatesAutoresizingMaskIntoConstraints:NO];//  绑定视图  在 [] 中使用 这样才能找到相应的控件NSDictionary *views =  NSDictionaryOfVariableBindings(imageView,label); //注意这是一个宏定义方法 等效与 @{@"imageView":imageView ,@"label":label}【具有自定义别名功能】;// 设置参数(度量)字典  变量数值动态化NSDictionary *metris = @{@"imageViewTop":@((self.bounds.size.height - image.size.height*2)/2),@"imageViewLeft":@((self.bounds.size.width - image.size.width*2)/2),@"imageViewHeight":@(image.size.height*2),@"imageViewWidth":@(image.size.width*2),};// 通过VFL语法添加约束组//placeholderView水平方向约束NSArray<NSLayoutConstraint *> *placeholderHConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-imageViewLeft-[imageView(imageViewHeight)]" options:0 metrics:metris views:views];//placeholderView和label垂直方向约束NSArray *placeholderVConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-imageViewTop-[imageView(imageViewWidth)]-20-[label]" options:0 metrics:metris views:views];//label水平方向约束NSArray *labelHConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[label]-0-|" options:0 metrics:metris views:views];// 将约束添加在父视图上[placeholderView addConstraints:labelHConstraints];[placeholderView addConstraints:placeholderHConstraints];[placeholderView addConstraints:placeholderVConstraints];[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[placeholderView(width)]" options:0 metrics:@{@"width":@(self.bounds.size.width)} views:NSDictionaryOfVariableBindings(placeholderView)]];[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[placeholderView(height)]" options:0 metrics:@{@"height":@(self.bounds.size.height)} views:NSDictionaryOfVariableBindings(placeholderView)]];//    // 疑问???  为什么下面的约束会导致 placeholderView高度和宽度为0
//
//    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[placeholderView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(placeholderView)]];
//    [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[placeholderView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(placeholderView)]];}

解决两个控件挤压问题

比如水平线上有两个label.文字较长,可能会导致某个label被压缩,比如这里我们需要红label不压缩。

普通解决办法:将红色label固定宽度大于等于

缺点:万一红label内容没有那么多,岂不是浪费空间了。

可以通过设置控件的优先级priority

ContentHuggingPriority:抗拉伸值,默认值251,值越大,越不容易被拉伸。

ContentCompressionResistancePriority:抗压缩值,默认呢为750,值越大,越不容易被压缩。

比如下图,我想让红色的label完整显示出来,你就可以将红label的抗压缩优先级设置高过与绿色label.

默认优先级显示效果

选中控件,选择Size Inspector,找到constains模块,修改优先级

设置抗压缩优先级

当然,也可以通过代码设置:

label.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 250), for: UILayoutConstraintAxis.horizontal) //设置水平抗压缩优先级
label.setContentHuggingPriority(UILayoutPriority(rawValue: 251), for: UILayoutConstraintAxis.horizontal) //设置水平抗拉伸优先级

修正后的效果图:

保持红label不被压缩

这个优先级和约束的优先级是同一比较水平的,如果你想让控件保持不拉伸不压缩就将它的优先级设置高于其他约束。

iOS自动布局-VFL格式约束相关推荐

  1. 自动布局 VFL 教程

    原文:Auto Layout Visual Format Language Tutorial 作者:József Vesza 译者:kmyhy 更新说明:本教程由 József Vesza 升级至 i ...

  2. 微信小程序IOS机型时间格式显示NaN异常问题

    new Date()转换时间时,IOS机型时间格式显示NaN 错误原因: ios不支持时间为2020-05-29这种格式的日期,必须转换为2020/05/29这种格式才能使用new Date()进行转 ...

  3. 微信小程序解决ios端时间格式兼容的问题

     微信小程序获取当时时间new Date时,会在ios真机上出现问题,具体表现为时间格式会报错并显示出NaN.这个bug并不会在模拟器和安卓系统出现,只会在ios系统上出现,具体原因是ios不支持符号 ...

  4. 关于微信小程序iOS端时间格式兼容问题

    关于微信小程序iOS端时间格式兼容问题 在自己开发中,当时间格式为 2020-06-29 08:00 ,需要将时间转为其他格式时,Android端转换成功,iOS端报错或是转为NaN. 解决方法: 1 ...

  5. iOS 自动布局框架 – Masonry 详解

    来源:伯乐在线 - 刘小壮 如有好文章投稿,请点击 → 这里了解详情 如需转载,发送「转载」二字查看说明 目前iOS开发中大多数页面都已经开始使用Interface Builder的方式进行UI开发了 ...

  6. iOS自动布局框架-Masonry详解

    目前iOS开发中大多数页面都已经开始使用Interface Builder的方式进行UI开发了,但是在一些变化比较复杂的页面,还是需要通过代码来进行UI开发的.而且有很多比较老的项目,本身就还在采用纯 ...

  7. 更加优雅的iOS自动布局

    因为懒,所以之前几乎不用代码进行自动布局.但是使用xib和storyboard,总是有那么一些局限性.使用代码布局在某些时候就成了必须了?  . iOS原生的布局方式太过麻烦.要么使用VFL(Visu ...

  8. iOS自动布局进阶用法

    本文主要介绍几个我遇到并总结的相对高级的用法(当然啦牛人会觉得这也不算什么). 简单的storyboard中上下左右约束,固定宽高啥的用法在这里就不做赘述了. autolayout自动布局是iOS6以 ...

  9. ios怎么引入masonry_详解 iOS 自动布局框架 Masonry

    集成方式 Masonry支持CocoaPods,可以直接通过podfile文件进行集成,需要在CocoaPods中添加下面代码: pod 'Masonry' Masonry 学习建议 在 UI 开发中 ...

最新文章

  1. Java对象表示方式2:XStream实现对对象的XML化
  2. 信令风暴研究现状总结
  3. java程序运行没有结果,求助啊!我刚学java 下面的程序一直运行但是没结果!!!...
  4. LotusScript (转)
  5. 从零基础入门Tensorflow2.0 ----八、40. keras分布式实战
  6. GdiPlus使用方法
  7. 【数据结构】天勤 例2-3 (单链表归并操作)二、递减
  8. 西安电子科大2010年的硕士博士考试推荐书
  9. soapUI Pro 4.5.1的新破解方案
  10. 什么是着色器 (Shader)占用率(Occupancy)? 为什么我们应该关心它?
  11. 《老路用得上的商学课》96-100学习笔记
  12. 《光剑文集》自渡:125首
  13. macbook proa1708_MacBook Pro 2017 A1708自己更换电池
  14. 刚开始做微商如何引流 ?一开始做微商没有客源怎么办
  15. 【游戏开发创新】当我学了Blender 建模,自制3D电脑桌面,回收站爆发了,把我做的模型都吐了出来(Blender | Unity | FBX)
  16. mysql 校对规则作用_讲讲Mysql中的校对规则究竟是怎么一回事
  17. 监狱筹建牌竖近2年 未告知民众关押病犯遭质疑
  18. nginx重启报找不到nginx.pid的解决方法
  19. 东西方赌王“口水战”升级 措词激烈论“竞争”
  20. AD的单端输入和查分输入

热门文章

  1. windows搭建gcc开发环境(msys2) objdump
  2. 梳理:python—同一个类中的方法调用
  3. python中.whl文件下载,pandas
  4. openGL 坐标系的互相转换
  5. 学习类中的const和static类型
  6. 152斤了,离健康又近了一步
  7. 【科普】:10分钟看明白XML和JSON
  8. 12-----指令系统介绍
  9. 【DB2】db2命令Export与Import
  10. 51nod 1225 余数之和(数论)