亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

轉載自@機智的新手:使用AutoLayout中的VFL(Visualformatlanguage)--代碼實現自動布局

2019-11-14 19:27:52
字體:
來源:轉載
供稿:網友

 

本文將通過簡單的UI來說明如何用VFL來實現自動布局。在自動布局的時候避免不了使用代碼來加以優化以及根據內容來實現不同的UI。

一:API介紹

  1. NSLayoutConstraint API

1
2
3
4
NSLayoutConstraint
+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts
metrics:(NSDictionary *)metrics
views:(NSDictionary *)views;

參數介紹:

format:此參數為你的vfl語句,比如:@"H:|-[button]-|"

opts:枚舉參數,默認寫0,具體跟據你所實現的需求去選擇你想要的枚舉

metrics:這里是一個字典,當在format中使用了動態數據比如上現這句:@"H:|-[button(==width)]-|",表示這個button的寬度為width,那么這個參數去哪里找呢?就是在這個字典里面找到key對就的值,如果沒有找到這個值,app就會crash.

views:顧名思義,這是傳所有你在vfl中使用到的view,那在上面這句例子中的應該怎么傳呢?結果是這樣的:NSDictionaryOfVariableBindings(button).如果你使用到了多個view,就可以這樣NSDictionaryOfVariableBindings(button,button1,button3...),這個名字也要跟參數format中的一一對應,缺一不可.

2.UIView API

1
2
UIView
- (void)addConstraints:(NSArray *)constraints;

在上面1中返回值類型是NSArray,而現在這個方法的參數也剛好是一個NSArray類型。那么直接把上一個方法的返回值當作這個方法的參數就可以了。如果你有多個VFL,你也可以利用可變數組( NSMutableArray)把這多個VFL返回的數據拼在一起,然后再調用addConstraints:方法。

二:簡單的使用

1.單控件的使用(沒有與其他控制有關聯,比如空隙等)

新建一個單頁面項目Single View application),在項目里面加上下面這段代碼代碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#import "ViewController.h"
@interface ViewController ()
  
@end
  
@implementation ViewController
  
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button=[[UIButton alloc]init];
    [button setTitle:@"點擊一下" forState:UIControlStateNormal];
    button.translatesAutoresizingMaskIntoConstraints=NO;
    [button setBackgroundColor:[UIColor blackColor]];
    [self.view addSubview:button];
    NSArray *constraints1=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button]-|"
                            options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button)];
      
    NSArray *constraints2=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[button(==30)]"
                            options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button)];
      
    [self.view addConstraints:constraints1];
    [self.view addConstraints:constraints2];
     
      
}
  
@end

運行程序,效果圖如下:

01222.jpg

可以看到,我們新建的button已經出來,證明上面的自動布局語句(VFL)已經生效。那么我們來詳細看看這些語句的意義是什么。

1
2
3
4
NSArray *constraints1=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button]-|"
                         options:0
                         metrics:nil
                         views:NSDictionaryOfVariableBindings(button)];

這里的意思是:button在水平方向上距離它的superView,左右各20px,比如在這里他的大小就是320-20*2=280.在@"H:|-[button]-|"這個語句中,其中"H:"是表示這是水平方向上的約束,"|"是表示superView,"-"表示一個間隔空間,這個間隔如果是如superView之間的,那么就是20px,如果是兩個同級別的view,比如@"[button]-[button1]",那么這里表示的是8px.

1
2
3
4
NSArray *constraints2=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[button(==30)]"
                         options:0
                         metrics:nil
                         views:NSDictionaryOfVariableBindings(button)];

跟上面有點不同,@"V:|-20-[button(==30)]",其中"V:"中代表這是垂直方向上的約束,"|-20-"這里的意思就是距離頭部為20px,相當于y坐標為20。后面的"[button(==30)]",是指定這個button的高度為30px.y坐標固定了,高度固定了,那這個view的約束就完成了。如果你有需要,你的高度值(或者其他同類型的)可以使用>=,==,<=來表示,甚至你可以組合來用,像上面的30,你可以指定一個區別,比如:(>=30,<=40),這同樣也是可以的。如果你想表達他的優先級別,可以使用@"V:|-20-[button(==30@1000)]",這個@1000,就是他的級別了。你可以適配XIB或者SB對它的優先級做更多的處理.

PS:值得注意的是,在用代碼創建的UIView在,一定要加上下面這句代碼

1
button.translatesAutoresizingMaskIntoConstraints=NO;

如果沒有上面這一行,你的約束將不生效,控制臺會輸出一連串的錯誤.

2:多控件之間關聯使用

基于上面的代碼上,我們重新加了一段代碼,現在的全部代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#import "ViewController.h"
@interface ViewController ()
  
@end
  
@implementation ViewController
  
- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button=[[UIButton alloc]init];
    [button setTitle:@"點擊一下" forState:UIControlStateNormal];
    button.translatesAutoresizingMaskIntoConstraints=NO;
    [button setBackgroundColor:[UIColor blackColor]];
    [self.view addSubview:button];
    NSArray *constraints1=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button]-|"
                           options:0
                           metrics:nil
                            views:NSDictionaryOfVariableBindings(button)];
      
    NSArray *constraints2=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[button(==30)]"
                            options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button)];
      
    [self.view addConstraints:constraints1];
    [self.view addConstraints:constraints2];
      
      
    UIButton *button1=[[UIButton alloc]init];
    button1.translatesAutoresizingMaskIntoConstraints=NO;
    [button1 setTitle:@"請不要點擊我" forState:UIControlStateNormal];
    [button1 setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:button1];
      
    NSArray *constraints3=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button1]-|"
                             options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button1)];
      
    NSArray *constraints4=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-[button1(==30)]"
                            options:0
                            metrics:nil
                            views:NSDictionaryOfVariableBindings(button1,button)];
      
    [self.view addConstraints:constraints3];
    [self.view addConstraints:constraints4];
      
}

運行的效果圖如下:

022.jpg

通過代碼對比,可以看出,在button1的垂直方向約束上,我們做了一點改變。水平方向上跟button一樣,這里就不多作解釋。我們來看看垂直方向上的。

1
2
3
4
NSArray *constraints4=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-[button1(==30)]"
                         options:0
                         metrics:nil
                         views:NSDictionaryOfVariableBindings(button1,button)];

VFL語句為:@"V:[button]-[button1(==30)]",這里用到了兩個view在VFL語句里面。剛才我們也說到,"-"在同一級別的View上使用的時候表示的間距為8個像素點,整一句的意思就是button1的y坐標離button有8個像素點.在不使用auto layout的時候,可以這樣表達CGRectGetMaxY(button.frame)+8.

我再改一下上面這一句VFL

1
2
3
4
NSArray *constraints4=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-[button1(==height)]"
                         options:0
                         metrics:@{@"height":@30}
                         views:NSDictionaryOfVariableBindings(button1,button)];

再次運行,你會發現,效果是一樣的。這樣你就知道怎么動態去給view加上高度或者寬度,或是其他間距了吧?

那么,如何做到兩個View,或是多個View之間等高,或者等寬呢?能用VFL可以做到嗎?除了通過上面的直接賦值寬高的數值外,VFL還提供了另外一種寫法用于等寬等高上。

還是上面的Demo,我們改一下代碼

1
2
3
4
5
6
7
8
9
NSArray *constraints3=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button1(button)]"
                         options:0
                         metrics:nil
                         views:NSDictionaryOfVariableBindings(button1,button)];
      
    NSArray *constraints4=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-[button1(button)]"
                           options:0
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(button1,button)];

通過@"H:|-[button1(button)]",@"V:[button]-[button1(button)]",這兩句就可以輕松實現等寬等高了!

三:最后對格式的字符串作一個總結介紹

功能        表達式

水平方向          H:

垂直方向          V:

Views         [view]

SuperView      |

關系         >=,==,<=

空間,間隙       -

優先級        @value

希望對各位讀者有所幫助,如果不妥的地方還望指出.


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一性一乱一交一视频| 欧美人与性动交| 一区二区在线免费视频| 国色天香2019中文字幕在线观看| 欧美性猛交xxxxx免费看| 欧美精品第一页在线播放| 欧美在线视频在线播放完整版免费观看| 国产精品视频久| 国产+成+人+亚洲欧洲| 91免费视频国产| 国产精品欧美亚洲777777| 日韩中文字幕精品| 国内免费精品永久在线视频| 欧美壮男野外gaytube| 国产91ⅴ在线精品免费观看| 欧美成人精品不卡视频在线观看| 国产欧美最新羞羞视频在线观看| 国产精品激情av电影在线观看| 91精品久久久久久久久久另类| 欧美国产高跟鞋裸体秀xxxhd| 日韩欧美在线看| 日本欧美黄网站| 日韩av成人在线观看| 成人黄色av免费在线观看| 欧美在线视频免费观看| 欧美成人午夜剧场免费观看| 精品久久中文字幕| 国产欧美精品一区二区三区-老狼| 日韩欧美国产视频| 成人妇女淫片aaaa视频| 精品视频在线导航| 欧美日韩一区二区三区| 日韩在线免费视频观看| 国产精品美乳一区二区免费| 久久久久久12| 亚洲成人xxx| 亚洲精品国精品久久99热一| 欧美大片网站在线观看| 日韩不卡中文字幕| 亚洲成人网久久久| 欧美大片免费观看在线观看网站推荐| 91精品免费久久久久久久久| 色婷婷成人综合| 欧美大片在线看免费观看| 欧美日韩一区二区免费在线观看| 最新的欧美黄色| 91久久久久久久久久久久久| 久久99精品久久久久久青青91| 亚洲欧洲一区二区三区在线观看| 欧美精品成人91久久久久久久| 91欧美日韩一区| 美日韩精品免费视频| 国产视频999| 一区二区福利视频| 久久综合88中文色鬼| 亚洲免费伊人电影在线观看av| 亚洲天堂精品在线| 琪琪亚洲精品午夜在线| xxxxx成人.com| 亚洲老头同性xxxxx| 国产亚洲精品久久久| 国产精品欧美日韩| 国产亚洲精品久久久久久| 精品久久久久久中文字幕一区奶水| 亚洲一级黄色av| 91国产一区在线| 91极品视频在线| 久久av红桃一区二区小说| 欧美成年人视频| 粗暴蹂躏中文一区二区三区| 久久免费少妇高潮久久精品99| 精品视频在线观看日韩| 日韩亚洲欧美成人| 欧美精品aaa| 亚洲激情视频网| 91九色单男在线观看| 国产精品视频免费在线| 国产午夜精品视频免费不卡69堂| 久久久精品在线观看| 久久影视免费观看| 上原亚衣av一区二区三区| 亚洲欧美国产精品专区久久| 亚洲日韩中文字幕在线播放| 国产精品第1页| 久久99久久久久久久噜噜| 欧美亚洲另类制服自拍| 91精品国产高清| 色噜噜狠狠狠综合曰曰曰| 亚洲福利在线播放| 欧美福利视频网站| 欧美性色视频在线| 日韩av在线电影网| 在线观看中文字幕亚洲| 91精品国产综合久久久久久蜜臀| 久久久久中文字幕| 欧美成人h版在线观看| 精品女同一区二区三区在线播放| 欧美成人合集magnet| 日韩在线中文字幕| 中文字幕最新精品| 91po在线观看91精品国产性色| 久久久噜久噜久久综合| 国产在线视频2019最新视频| 91成人精品网站| 亚洲中国色老太| 国产精品午夜一区二区欲梦| 成人免费xxxxx在线观看| 久久影院资源网| 欧美色另类天堂2015| 欧美在线一区二区视频| 欧美一区三区三区高中清蜜桃| 97久久超碰福利国产精品…| 亚洲伊人一本大道中文字幕| 国产精品99久久99久久久二8| 日本成人精品在线| 久久精品99久久香蕉国产色戒| 国产成人精品免费久久久久| 久久电影一区二区| 在线播放国产一区中文字幕剧情欧美| 亚洲性线免费观看视频成熟| 亚洲欧美国产精品专区久久| 欧美精品福利视频| 欧美激情一级精品国产| 亚洲天堂av女优| 国产精品影院在线观看| 国产精品久久久久久久久久99| 亚洲在线www| 日韩性生活视频| 性色av香蕉一区二区| 久久久久亚洲精品| 亚洲精品国产欧美| 色偷偷综合社区| 亚洲免费视频一区二区| 欧美黑人xxxx| 日韩小视频网址| 亚洲一区二区三区777| 久久99国产精品久久久久久久久| 亚洲天堂一区二区三区| 欧美亚洲另类制服自拍| 欧美高清自拍一区| 美女av一区二区三区| 日韩精品福利网站| 日韩精品www| 欧美极品在线视频| 2019亚洲男人天堂| 欧美精品久久久久| 欧美影院久久久| 成人免费观看a| 91亚洲精品久久久| 国产91在线视频| 欧美精品在线观看| 国产日韩av在线播放| 欧美老女人www| 国产精品成人久久久久| 日韩h在线观看| 亚洲第一区第一页| 国产亚洲美女久久| 91久久在线播放| 亚洲xxxx视频| 国产成人精品视| 成人黄色av网站| 日av在线播放中文不卡| 亚洲人成电影网| 久久人体大胆视频|