常见问题总结篇二、 对Autolayout VFL(Visual Format Language) 的扩展

简介
当年苹果放出VFL时,着实花了好几天来试验,熟悉它
对于它的利弊已经有很多朋友的文章讨论过了,不在赘述
我关心的点在于它的不完备性,即没法用VFL来完成所有的约束布局

 One useful constraint that cannot be expressed is a fixed aspect ratio (for example,  imageView.width = 2 * imageView.height ). To create such a constraint, you can use  constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: .(来源:Auto Layout Guide)

这时候我们就要用
[NSLayoutConstraint constraintWithItem:self.button1 attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.button2 attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-12.0];
说实话,这个表达形式太丑陋了,所以这篇文章的目的就是扩展VFL的语法,使它能表达 “ fixed aspect ratio”。
然后我们可以使用 @“button1.Right=button2.Left*1.0-12” 来代替那么长一串代码了

不多说先看结果:


界面描述:
  1. 上图所有空白处的间距都是10
  2. right1 固定宽高
  3. left1 高度为right1高度的一半减10,宽度自适应
  4. left2 高度比left1大20,与left1水平对齐,宽度相等
  5. right2 left3 高宽相等,高度固定
  6. right3 填充剩下的部分
对应添加约束代码:
-( void )installConstraintsByExtension
{
    
NSDictionary * viewsDictionary= NSDictionaryOfVariableBindings ( _rightView1 , _rightView2 , _rightView3 , _leftView1 , _leftView2 , _leftView3 );
    
NSArray * constraintStrings= @[
                                     
@"V:|-74-[_rightView1]-10-[_rightView2]-10-[_rightView3]-10-|" ,
                                     
                                     
@"H:|-10-[_rightView1]-10-[_leftView1]-10-|" ,
                                     
@"H:[_rightView1(100@1000)]" ,
                                     
@"V:[_rightView1(200@1000)]" ,
                                     
                                     
@"_leftView1.Top=_rightView1.Top" ,
                                     
@"V:[_leftView1][_leftView2]" ,
                                     
@"_leftView1.Left=_leftView2.Left" ,
                                     
@"_leftView1.Height=_rightView1.Height*0.5-10" ,
                                     
@"_leftView2.Height=_leftView1.Height+20.0f" ,
                                     
@"[_leftView1(==_leftView2)]" ,
                                     
                                     
@"H:|-10-[_rightView2]-10-[_leftView3]-10-|" ,
                                     
@"H:[_rightView2(==_leftView3)]" ,
                                     
@"V:[_rightView2(==_leftView3)]" ,
                                     
@"V:[_rightView2(200@1000)]" ,
                                     
@"_leftView3.Top=_rightView2.Top" ,
                                     
                                     
@"H:|-10-[_rightView3]-10-|" ,
                                 
] ;
    
    [
NSLayoutConstraint   activateConstraints : VFL (constraintStrings, viewsDictionary)];
}
思路如下:
  • 确定语法形式
其实就是一个简单的 objectA.attributeA=objectB.attributeB*multiplier+constant 表达式
为了不和已有的VFL混淆,我们需要识别这种模式,这时候我们要用到正则表达式了,其遵循的模式(以后有机会再解释)为:
#define Pattern @ "[a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*[><=][a-zA-Z_][a-zA-Z0-9_]*\\.[a-zA-Z_][a-zA-Z0-9_]*(\\*[0-9]+(\\.[0-9]+f?)?)?([\\+-][0-9]+(\\.[0-9]+f?)?)?"
  • 将字符串解析为约束
这时候,我们需要从字符串中获取信息,构造出一个 constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:约束来
所以,我们需要从表达式中
  1. 获取对象objectA objectB 与实际对象的对应关系
    • 在解析时传入对象的键值对字典即可
  2. 获取attributeA,attributeB与 NSLayoutAttribute的对应关系
    • 一个全局的属性名称对应字典
  3. 获取倍率和常数
  4. 获取属性间的关系
    • = 代表NSLayoutRelationEqual 
    • <  代表 NSLayoutRelationLessThanOrEqual
    • > 代表NSLayoutRelationGreaterThanOrEqual
具体实现见源码: https://github.com/sunuo/Tests.git
语法说明:
      objectA.attributeA=objectB.attributeB*multiplier+constant
  1. 对象和属性的名字由数字字母下划线组成,而且以字母开头,所以要想正确解析出对象的键,不能用self.objectA.attributeA的形式
  2. multiplier和constant可以不写,此事默认multiplier=1 constant=0
  3. 当表达式中包含multiplier、constant时,它们必须出现在objectB.attributeB之后
正确语法举例:
  1. view1.Top=view2.Top
  2. view1.Top>view2.Top+1
  3. view1.Top<view2.Top*3
  4. view1.Top<view2.Top*3+1.0f





 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值