因為工作原因,需要用到VFL卷玉,所以在放假期間不得不研究一下VFL的使用,很多地方仍然不熟悉喷市,在次記錄下使用方法相种。
VFL基本語法介紹
功能 表達式
水平方向 H:
垂直方向 V:
Views [view]
SuperView |
關系 >=,==,<=
空間,間隙(默認值8) -
優(yōu)先級 @value
舉例示范
語法示例 | 圖片展示 | 語法介紹 |
---|---|---|
H:[button]-[textField] | standard Space
|
設置視圖間距 |
H:[button(>=50)] | Width Constraint
|
設置寬度大于等于50 |
connectionToSuperView
|
距父視圖左右邊距50 | |
V:[topField-10-[bottomField]] | VerticalLayout
|
豎直方向設置間距 |
H:[maroonView][blueView] | 對齊 | |
H:[button(@200)] | 設置優(yōu)先級 | |
H:[button1(==button2)] | 等寬 | |
[flexibleButton(>=70,<=100)] | 多個謂語設置尺寸 |
第三句的語法,應為"H:|-50-[purpleBox]-50-|",因為與MarkDown表格語法沖突品姓,所以無法顯示"|",在此處更正下.
VFL API
NSLayoutConstraint
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
參數介紹:
format:此參數就是我們需要設置的VFL語句寝并,如 "|H:-50-[purpleBox]-50-|"
options:枚舉參數,默認寫0腹备,具體跟你你所實現的需求去選擇你想要的枚舉衬潦。
metrics:這里是一個字典,當在format中使用了動態(tài)數據比如上現這句:@"H:|-[button(==width)]-|",表示這個button的寬度為width,那么這個參數去哪里找呢植酥?就是在這個字典里面找到key對就的值镀岛,如果沒有找到這個值,app就會crash.
views:顧名思義友驮,這是傳所有你在vfl中使用到的view漂羊,那在上面這句例子中的應該怎么傳呢?結果是這樣的:NSDictionaryOfVariableBindings(button).如果你使用到了多個view喊儡,就可以這樣NSDictionaryOfVariableBindings(button,button1,button3...),這個名字也要跟參數format中的一一對應拨与,缺一不可.
NSLayoutConstraint
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
參數介紹:
view1:需要添加約束的view
attr1:枚舉稻据,添加約束對應的屬性艾猜,例如:NSLayoutAttributeLeft;
relation:枚舉捻悯,添加約束與關聯的view之間的關系匆赃,關系有 ==, >= ,<=
view2:添加約束需要關聯的view
attr2:關聯的view對應的屬性
multiplier:與關聯view對應屬性的倍數關系
constraint:約束值
UIView API
UIView
- (void)addConstraints:(NSArray *)constraints;
在VFL的第一個API中返回值類型是NSArray,而現在這個方法的參數也剛好是一個NSArray類型今缚。那么直接把上一個方法的返回值當作這個方法的參數就可以了算柳。如果你有多個VFL,你也可以利用可變數組( NSMutableArray)把這多個VFL返回的數據拼在一起姓言,然后再調用addConstraints:方法瞬项。
UIView
- (void)addConstraint:(NSLayoutConstraint *)constraint;
在VFL的第二個API中返回值類型是NSLayoutConstraint蔗蹋,現在這個方法的參數也是NSLayoutConstraint。那么直接把上一個方法的返回值當作這個方法的參數就可以了囱淋。
代碼示例
現在我們有一個需求猪杭,頁面中有一張圖片和一段文字,我們需要圖片距離父視圖左邊和上邊各20妥衣,寬高固定為80皂吮,文字距圖片下方20,父視圖左邊20税手,寬高根據文本內容變化蜂筹。
如下圖:
根據以上的需求,實現代碼如下:
//初始化ImageView
UIImageView *imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"2.jpg"];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:imageView];
//初始化Label
UILabel *label = [UILabel new];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.text = @"這是一個優(yōu)美的句子芦倒。";
[self.view addSubview:label];
//imageView的約束設置
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(imageView);
NSArray *imageViewHorizontalContriants = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[imageView(==80)]" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:imageViewHorizontalContriants];
NSArray *imageViewVerticalContriants = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[imageView(==80)]" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:imageViewVerticalContriants];
//label的約束設置
NSArray *labelHorizontalContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[label]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)];
[self.view addConstraints:labelHorizontalContraints];
NSArray *labelVerticalContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageView]-20-[label]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imageView,label)];
[self.view addConstraints:labelVerticalContraints];
現在我們的需求改變一下艺挪,我們需要圖片和文字居中對齊。
這樣的話熙暴,我們可以把約束代碼更新如下:
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(imageView);
NSArray *imageViewHorizontalContriants = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[imageView(==80)]" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:imageViewHorizontalContriants];
NSArray *imageViewVerticalContriants = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[imageView(==80)]" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:imageViewVerticalContriants];
NSLayoutConstraint *imageViewConstraint = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.view addConstraint:imageViewConstraint];
NSArray *labelVerticalContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageView]-20-[label]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imageView,label)];
[self.view addConstraints:labelVerticalContraints];
NSLayoutConstraint *labelConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
[self.view addConstraint:labelConstraint];
下面把需求難度提升一下闺属,我們需要文字可以自動換行,而且距父視圖大于等于10周霉。
添加label的約束代碼如下:
label.numberOfLines = 0;
NSArray *labelHorizantalContraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|->=10-[label]->=10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(label)];
[self.view addConstraints:labelHorizantalContraints];