Autolayout屏幕適配——代碼實現(蘋果公司 / VFL語言 / 第三方框架Masonry)

 

在講解如何經過代碼來實現屏幕適配前,先來了解一下,屏幕適配中用到的約束添加的規則。git

    在建立約束以後,須要將其添加到做用的view上
    在添加時要注意目標view須要 遵循如下規則

1. 約束規則

   1> 添加約束的規則(一)   

     對於兩個同層級view之間的約束關係,添加到它們的父view上

   

   2> 添加約束的規則(二)   

      對於兩個不一樣層級view之間的約束關係,添加到他們最近的共同父view上
     

   3> 添加約束的規則(三)   

      對於有層次關係的兩個view之間的約束關係,添加到層次較高的父view上
     

小案例:Autolayout動畫:

用代碼來採用動畫形式移動小紅view:github

 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 /**
 6  *  直接將用到的約束和紅色View拖拽到控制器中,以便使用.
 7  */
 8 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightCos;
 9 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *topCos;
10 @property (weak, nonatomic) IBOutlet UIView *redView;
11 @end
12 
13 @implementation ViewController
14 
15 - (void)touchesBegan:(nonnull NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
16 {
17 //    NSLog(@"%f", self.heightCos.constant);
18 //    self.heightCos.constant += 50;
19     self.topCos.constant += 150;
20     [UIView animateWithDuration:2.0 animations:^{
21         // 強制更新界面
22         // 會更新當前控件和當前控件全部的子控件
23         [self.redView layoutIfNeeded];
24     }];
25 }
26 
27 @end
View Code

小案例:紅色View是藍色View寬度一半.....約束實現:

  1 //
  2 //  ViewController.m
  3 
  4 #import "ViewController.h"
  5 
  6 @interface ViewController ()
  7 
  8 @end
  9 
 10 @implementation ViewController
 11 
 12 - (void)viewDidLoad {
 13     [super viewDidLoad];
 14     // Do any additional setup after loading the view, typically from a nib.
 15     
 16     /**
 17      1. 實現紅色View是藍色View寬度的一半,等。
 18      */
 19 
 20     // 1.建立兩個控件, 而且添加到父控件上
 21     UIView *blueView = [[UIView alloc] init];
 22     blueView.backgroundColor = [UIColor blueColor];
 23     [self.view addSubview:blueView];
 24     
 25     UIView *redView = [[UIView alloc] init];
 26     redView.backgroundColor = [UIColor redColor];
 27     [self.view addSubview:redView];
 28     
 29     
 30     // 2.添加約束
 31 //    self.view.translatesAutoresizingMaskIntoConstraints = NO; // 錯誤寫法, 禁用父控件的對子控件無效
 32     
 33     redView.translatesAutoresizingMaskIntoConstraints = NO;
 34     blueView.translatesAutoresizingMaskIntoConstraints = NO;
 35     
 36     // 2.1添加藍色的約束
 37     // 2.1.1頂部
 38     NSLayoutConstraint *blueTopCos = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:20];
 39     [self.view addConstraint:blueTopCos];
 40     
 41     // 2.1.2左邊
 42     NSLayoutConstraint *blueLeftCos = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
 43     [self.view addConstraint:blueLeftCos];
 44     
 45     
 46     // 2.1.3右邊
 47     NSLayoutConstraint *blueRightCos = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
 48     [self.view addConstraint:blueRightCos];
 49     
 50     // 2.1.4高度
 51     NSLayoutConstraint *blueHeightCos = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:50];
 52     [blueView addConstraint:blueHeightCos];
 53     
 54     
 55     // 2.2添加紅色的約束
 56     // 2.2.1頂部
 57     NSLayoutConstraint *redTopCos = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20];
 58     [self.view addConstraint:redTopCos];
 59     
 60     // 2.2.2右邊
 61     NSLayoutConstraint *redRightCos = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
 62     [self.view addConstraint:redRightCos];
 63     
 64     // 2.2.3高度
 65     NSLayoutConstraint *redHeightCos = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:50];
 66     [redView addConstraint:redHeightCos];
 67     
 68     // 2.2.4寬度
 69     NSLayoutConstraint *redWidthCos = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];
 70     [self.view addConstraint:redWidthCos];
 71 
 72     
 73 }
 74 
 75 
 76 - (void)demo1
 77 {
 78     
 79     // 1.建立控件
 80     UIView *redView = [[UIView alloc] init];
 81     redView.backgroundColor = [UIColor redColor];
 82     [self.view addSubview:redView];
 83     
 84     // 2.建立約束
 85     /*
 86      Item == first item
 87      attribute == first item須要設置的約束類型
 88      relatedBy == Relatio(等於)
 89      toItem ==  Second item
 90      attribute == Second item的約束類型
 91      multiplier == 乘以
 92      constant == 加上多少
 93      */
 94     
 95 #warning 注意點: 若是經過代碼來設置Autolayout約束, 那麼必須先禁用Autoresizing
 96     redView.translatesAutoresizingMaskIntoConstraints = NO;
 97     
 98     // 2.1寬度
 99     NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:100.0];
100     // 將約束添加給本身
101     [redView addConstraint:width];
102     
103     // 2.2高度
104     NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:kNilOptions multiplier:1.0 constant:100.0];
105     // 將約束添加給本身
106     [redView addConstraint:height];
107     
108     // 2.3水平居中
109     NSLayoutConstraint *xCos = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
110     // 將約束添加到層次較高的父view上
111     [self.view addConstraint:xCos];
112     
113     // 2.4垂直居中
114     NSLayoutConstraint *yCos = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
115     // 將約束添加到層次較高的父view上
116     [self.view addConstraint:yCos];
117     
118 #warning 注意: 經過代碼添加Autolayout約束, 添加約束以前必須保證控件已經在父控件上了
119     //    [self.view addSubview:redView];
120 }
121 @end
View Code

二、瞭解一下 VFL語言 來處理適配

   2.1 什麼是VFL語言

   VFL全稱是Visual Format Language,翻譯過來是「可視化格式語言」
   VFL是蘋果公司爲了簡化Autolayout的編碼而推出的抽象語言
  

 2.2  VFL示例   

 1 H:[cancelButton(72)]-12-[acceptButton(50)]
 2//  canelButton寬72,acceptButton寬50,它們之間間距12
 3 
 4 H:[wideView(>=60@700)]
 5 // wideView寬度大於等於60point,該約束條件優先級爲700(優先級最大值爲1000,優先級越高的約束越先被知足)
 6 
 7 V:[redBox][yellowBox(==redBox)]
 8 // 豎直方向上,先有一個redBox,其下方緊接一個高度等於redBox高度的yellowBox
 9 
10 H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
11 // 水平方向上,Find距離父view左邊緣默認間隔寬度,以後是FindNext距離Find間隔默認寬度;再以後是寬度不小於20的FindField,它和FindNext以及父view右邊緣的間距都是默認寬度。(豎線「|」 表示superview的邊緣

2.3  VFL的使用

1  // 使用VFL來建立約束數組
2 + (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
3 format :VFL語句
4 opts :約束類型
5 metrics :VFL語句中用到的具體數值
6 views :VFL語句中用到的控件
7 
8 // 建立一個字典(內部包含VFL語句中用到的控件)的快捷宏定義
9 NSDictionaryOfVariableBindings(...)

2.4VFL適配小案例:

 1.  在控制器view底部添加2個view,1個藍色,1個紅色數組

     2個view寬度、高度永遠相等
     距離父控件左邊、右邊、下邊間距和2個view之間的間距相等
 1 - (void)demo1
 2 {
 3     // 1.建立一個紅色View, 而且添加到父控件
 4     UIView *redVeiw = [[UIView alloc] init];
 5     redVeiw.backgroundColor = [UIColor redColor];
 6     [self.view addSubview:redVeiw];
 7     
 8     // 2.禁止紅色View的Autgoresizing
 9     redVeiw.translatesAutoresizingMaskIntoConstraints = NO;
10     
11     // 3.利用VFL添加約束
12     /*
13      VisualFormat: VFL語句
14      options: 對齊方式等
15      metrics: VFL語句中使用到的一些變量
16      views: VFL語句中使用到的一些控件
17      */
18     NSArray *hCos = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-margin-[xxxVeiw(==width)]" options:kNilOptions metrics:@{@"margin": @(20), @"width":@(100)} views:@{@"xxxVeiw": redVeiw}];
19     [self.view addConstraints:hCos];
20     
21     NSArray *vCos = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[xxxVeiw(==100)]" options:kNilOptions metrics:nil views:@{@"xxxVeiw": redVeiw}];
22     [self.view addConstraints:vCos];
23 }
View Code

2. 在控制器view頂部添加2個view,1個藍色,1個紅色框架

    2個view高度永遠相等
    紅色view和藍色view右邊對齊
   藍色view距離父控件左邊、右邊、上邊間距相等
   藍色view距離紅色view間距固定
   紅色view的左邊和父控件的中點對齊

以下爲實現代碼:ide

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     // 1.建立一個紅色View, 而且添加到父控件
 4     UIView *blueVeiw = [[UIView alloc] init];
 5     blueVeiw.backgroundColor = [UIColor blueColor];
 6     [self.view addSubview:blueVeiw];
 7     
 8     UIView *redVeiw = [[UIView alloc] init];
 9     redVeiw.backgroundColor = [UIColor redColor];
10     [self.view addSubview:redVeiw];
11  
12     // 2.禁止紅色View的Autgoresizing
13     blueVeiw.translatesAutoresizingMaskIntoConstraints = NO;
14     redVeiw.translatesAutoresizingMaskIntoConstraints = NO;
15     
16     // 3.利用VFL添加約束
17     /*
18      VisualFormat: VFL語句
19      options: 對齊方式等
20      metrics: VFL語句中使用到的一些變量
21      views: VFL語句中使用到的一些控件
22      */
23     // 3.1設置藍色
24     // 3.1.1水平方向
25     NSArray *blueHCos = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[blueVeiw]-20-|" options:kNilOptions metrics:nil views:@{@"blueVeiw":blueVeiw}];
26     [self.view addConstraints:blueHCos];
27     
28     // 3.1.2垂直方向
29     NSArray *blueVCos = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[blueVeiw(==50)]" options:kNilOptions metrics:nil views:@{@"blueVeiw":blueVeiw}];
30      [self.view addConstraints:blueVCos];
31     
32     // 3.2設置紅色
33     // 3.2.1垂直方向
34     NSArray *redVCos = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[blueVeiw]-20-[redVeiw(==50)]" options:NSLayoutFormatAlignAllRight metrics:nil views:@{@"blueVeiw":blueVeiw, @"redVeiw":redVeiw}];
35     [self.view addConstraints:redVCos];
36     
37     // 3.2.2水平方向
38 //    NSArray *redHCos = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[redVeiw(==blueVeiw * 0.5)]" options:kNilOptions metrics:nil views:@{@"blueVeiw":blueVeiw, @"redVeiw":redVeiw}];
39 //    [self.view addConstraints:redHCos];
40     
41 #warning VFL不支持乘除法
42     NSLayoutConstraint *redHCos =[NSLayoutConstraint constraintWithItem:redVeiw attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueVeiw attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0.0];
43     [self.view addConstraint:redHCos];
44     
45 }
View Code

3. 利用第三方框架 Masonry,實現屏幕適配

  3.1 Masonry瞭解:動畫

      目前最流行的Autolayout第三方框架
      用優雅的代碼方式編寫Autolayout
      省去了蘋果官方噁心的Autolayout代碼
      大大提升了開發效率
 
  3.2 如何使用
     1> 導入到項目中,
     2> 導入頭文件: 
1 //define this constant if you want to use Masonry without the 'mas_' prefix
2 #define MAS_SHORTHAND
3 
4 //define this constant if you want to enable auto-boxing for default syntax
5 #define MAS_SHORTHAND_GLOBALS
6 #import "Masonry.h"

小案例實現代碼:this

  1 #import "ViewController.h"
  2 
  3 //define this constant if you want to use Masonry without the 'mas_' prefix
  4 #define MAS_SHORTHAND 
  5 // 只要添加這個宏, 就能夠去掉Masonry框架中對象訪問對象屬性前面的mas_屬性, 和方法前的mas_前綴
  6 
  7 // 例如添加前的寫法
  8 /*
  9  make.left.equalTo(self.view.mas_left).with.offset(20);
 10  */
 11 // 例如添加後的寫法
 12 /*
 13  make.left.equalTo(self.view.left).with.offset(20);
 14  */
 15 
 16 
 17 //define this constant if you want to enable auto-boxing for default syntax
 18 #define MAS_SHORTHAND_GLOBALS
 19 // 只要添加上這個宏, 給equalTo傳遞參數的時候, 就能夠直接傳遞基本數據類型 ,系統會自動包裝
 20 // 若是沒有添加上面這個宏, 那麼給equalTo傳遞參數的時候, 必須傳遞對象
 21 // 若是要傳遞基本數據類型必須使用mas_equalTo
 22 
 23 
 24 // 只須要在導入Masonry.h以前, 添加上一上兩個宏, 就能夠簡化代碼
 25 #import "Masonry.h"
 26 
 27 @interface ViewController ()
 28 
 29 @property(nonatomic, weak)UIView *blueVeiw;
 30 @end
 31 
 32 @implementation ViewController
 33 
 34 
 35 
 36 - (void)viewDidLoad {
 37     [super viewDidLoad];
 38     // Do any additional setup after loading the view, typically from a nib.
 39     
 40     /**
 41      1. 實現紅色view是藍色寬度一半。。。。,如上案例二
 42      */
 43     
 44     // 1.建立兩個View, 而且添加到父控件
 45     UIView *blueVeiw = [[UIView alloc] init];
 46     blueVeiw.backgroundColor = [UIColor blueColor];
 47     [self.view addSubview:blueVeiw];
 48     self.blueVeiw = blueVeiw;
 49     
 50     UIView *redVeiw = [[UIView alloc] init];
 51     redVeiw.backgroundColor = [UIColor redColor];
 52     [self.view addSubview:redVeiw];
 53     
 54     // 2.禁止紅色View的Autgoresizing
 55     blueVeiw.translatesAutoresizingMaskIntoConstraints = NO;
 56     redVeiw.translatesAutoresizingMaskIntoConstraints = NO;
 57     
 58     // 3.添加藍色的約束
 59     [blueVeiw makeConstraints:^(MASConstraintMaker *make) {
 60         make.left.equalTo(self.view.left).offset(20);
 61         make.right.equalTo(self.view.right).offset(-20);
 62         make.top.equalTo(self.view.top).offset(20);
 63         make.height.equalTo(50);
 64     }];
 65     
 66     // 4.添加紅色的約束
 67     [redVeiw makeConstraints:^(MASConstraintMaker *make) {
 68         make.top.equalTo(blueVeiw.bottom).offset(20);
 69         make.height.equalTo(blueVeiw.height);
 70         make.right.equalTo(blueVeiw.right);
 71         make.width.equalTo(blueVeiw.width).multipliedBy(0.5);
 72     }];
 73 
 74 //    注意: 在Storyboard中約束是能夠重複添加的, 經過Masonry添加約束也是能夠重複的, 要注意重複添加致使的錯誤和衝突
 75     
 76 }
 77 
 78 - (void)touchesBegan:(nonnull NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event
 79 {
 80     /*
 81     // 使用makeConstraints, 每次都會添加新的約束, 也就是會致使重複添加
 82 //    [self.blueVeiw makeConstraints:^(MASConstraintMaker *make) {
 83 //        make.height.equalTo(100);
 84 //    }];
 85     
 86     // 要更新約束使用updateConstraints
 87     // updateConstraints特色: 若是沒有設置過, 就添加一個新的
 88     // 若是已經設置過了, 就更新之前設置的那一個
 89     [self.blueVeiw updateConstraints:^(MASConstraintMaker *make) {
 90         make.height.equalTo(100);
 91     }];
 92      */
 93     
 94     // 清空約束 remakeConstraints
 95     [self.blueVeiw remakeConstraints:^(MASConstraintMaker *make) {
 96         
 97     }];
 98 }
 99 
100 - (void)demo
101 {
102     // 1.建立一個控件
103     UIView *redVeiw = [[UIView alloc] init];
104     redVeiw.backgroundColor = [UIColor redColor];
105     [self.view addSubview:redVeiw];
106     
107     // 2.禁止紅色View的Autgoresizing
108     redVeiw.translatesAutoresizingMaskIntoConstraints = NO;
109     
110     // 3.利用Masonry添加約束
111     /*
112      [redVeiw mas_makeConstraints:^(MASConstraintMaker *make) {
113      
114      make.left.equalTo(self.view.mas_left).offset(20);
115      make.top.equalTo(self.view.mas_top).offset(20);
116      make.bottom.equalTo(self.view.mas_bottom).offset(-20);
117      make.right.equalTo(self.view.mas_right).offset(-20);
118      }];
119      */
120     
121     /*
122      [redVeiw mas_makeConstraints:^(MASConstraintMaker *make) {
123      
124      make.left.equalTo(self.view).offset(20);
125      make.top.equalTo(self.view).offset(20);
126      make.bottom.equalTo(self.view).offset(-20);
127      make.right.equalTo(self.view).offset(-20);
128      }];
129      */
130     
131     /*
132      [redVeiw mas_makeConstraints:^(MASConstraintMaker *make) {
133      
134      make.left.offset(20);
135      make.top.offset(20);
136      make.bottom.offset(-20);
137      make.right.offset(-20);
138      }];
139      */
140     
141     /*
142      [redVeiw mas_makeConstraints:^(MASConstraintMaker *make) {
143      make.edges.insets(UIEdgeInsetsMake(20, 20, 20, 20));
144      }];
145      */
146     
147     /*
148      [redVeiw mas_makeConstraints:^(MASConstraintMaker *make) {
149      
150      // 注意: 在masonry中with和and這兩個單詞是爲了提升閱讀性而存在的, 沒有意義
151 //        make.left.equalTo(self.view.mas_left).with.offset(20);
152 //        make.top.equalTo(self.view.mas_top).with.offset(20);
153 //        make.bottom.equalTo(self.view.mas_bottom).with.offset(-20);
154 //        make.right.equalTo(self.view.mas_right).with.offset(-20);
155      
156      // 要想這樣使用必須加上:#define MAS_SHORTHAND
157      // 不然只能使用 mas_left
158      make.left.equalTo(self.view.left).with.offset(20);
159      make.top.equalTo(self.view.top).with.offset(20);
160 //        make.width.equalTo(@(100));
161      
162      // 要想這樣使用必須加上:#define MAS_SHORTHAND_GLOBALS
163      make.height.equalTo(100);
164 //        make.width.and.height.equalTo(@(100)); // 只能接收對象
165      // mas_equalTo本質仍是接收對象, 仍是調用equalTo
166 //        make.width.and.height.mas_equalTo(100); // 能夠接收基本數據類型
167      
168      }];
169      */
170 }
171 
172 
173 @end
View Code

總結:累並快樂着,明天繼續更新,一塊兒進步,困的不行了,晚安,^_^編碼

相關文章
相關標籤/搜索