天天看點

【原】iOS學習之蘋果原生代碼實作Autolayout和VFL語言

1、添加限制的規則

  • 在建立限制之後,需要将其添加到作用的view上
  • 在添加時要注意目标view需要遵循以下規則:

  1)對于 兩個同層級view之間 的限制關系,添加到它們的父view上  

  2)對于 兩個不同層級view之間 的限制關系,添加到他們最近的共同父view上

  3)對于 有層次關系的兩個view之間 的限制關系,添加到層次較高的父view上

2、蘋果原生代碼實作Autolayout

  • 步驟

  1)利用NSLayoutConstraint類建立具體的限制對象

   1> 一個NSLayoutConstraint對象就代表一個限制

   2> 建立限制對象的常用方法      

+(id)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;      

   參數說明

    pview1 :要限制的控件

      pattr1 :限制的類型(做怎樣的限制)

      prelation :與參照控件之間的關系

      pview2 :參照的控件

      pattr2 :限制的類型(做怎樣的限制)

      pmultiplier :乘數

      pc :常量

  2)添加限制對象到相應的view上

    - (void)addConstraint:(NSLayoutConstraint *)constraint;

    - (void)addConstraints:(NSArray *)constraints;

  • 注意點

  1)要先禁止autoresizing功能,設定view的下面屬性為NO

   view.translatesAutoresizingMaskIntoConstraints = NO;      

   如果不設定為NO,系統會自動将AutoresizingMask轉為Autolayout的限制,進而造成限制沖突,控制台列印内容如下:

Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want. 

Try this: 

(1) look at each constraint and try to figure out which you don't expect; 

(2) find the code that added the unwanted constraint or constraints and fix it. 

(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 

(

    "<NSAutoresizingMaskLayoutConstraint:0x7ff339620540 h=--& v=--& V:[UIView:0x7ff339714510(0)]>",

    "<NSLayoutConstraint:0x7ff339714990 V:[UIView:0x7ff339714510(40)]>"

)

Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0x7ff339714990 V:[UIView:0x7ff339714510(40)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.

The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

  2)添加限制之前,一定要保證相關控件都已經在各自的父控件上,也就是将子控件添加到父控件上

  3)不用再給view設定frame

  • 代碼: 
   UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    // 不要将AutoresizingMask轉為Autolayout的限制
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];
    
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    // 不要将AutoresizingMask轉為Autolayout的限制
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];// 添加寬度限制:100
    
    /************************** 藍色 **************************/
    // 添加高度限制:40
    NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:40];
    [blueView addConstraint:heightConstraint];
    
    // 添加左邊限制:blueView的左邊距離父控件左邊有20的間距
    NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20];
    [self.view addConstraint:leftConstraint];
    
    // 添加右邊限制:blueView的右邊距離父控件右邊有20的間距
    NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20];
    [self.view addConstraint:rightConstraint];
    
    // 添加頂部限制:blueView的頂部距離父控件頂部有20的間距
    NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:20];
    [self.view addConstraint:topConstraint];
    
    /************************** 紅色 **************************/
    // 添加高度限制:藍色等高
    NSLayoutConstraint *heightConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0];
    [self.view addConstraint:heightConstraint2];
    
    // 添加左邊限制:redView的左邊 == 父控件的中心x
    NSLayoutConstraint *leftConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
    [self.view addConstraint:leftConstraint2];
    
    // 添加頂部限制:redView的頂部距離blueView的底部有20的間距
    NSLayoutConstraint *topConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20];
    [self.view addConstraint:topConstraint2];
    
    // 添加右邊限制:redView的右邊 == blueView的右邊
    NSLayoutConstraint *rightConstraint2 = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
    [self.view addConstraint:rightConstraint2];      

     效果圖如下:

3、VFL語言

  • 什麼是VFL語言

  VFL全稱是Visual Format Language,翻譯過來是“可視化格式語言”

  VFL是蘋果公司為了簡化Autolayout的編碼而推出的抽象語言

  • VFL示例:

  1)H:[cancelButton(72)]-12-[acceptButton(50)]

  canelButton寬72,acceptButton寬50,它們之間間距12

  2)H:[wideView(>=60@700)]

  wideView寬度大于等于60point,該限制條件優先級為700(優先級最大值為1000,優先級越高的限制越先被滿足)

  3)V:[redBox][yellowBox(==redBox)]

  豎直方向上,先有一個redBox,其下方緊接一個高度等于redBox高度的yellowBox

  4)H:|-10-[Find]-[FindNext]-[FindField(>=20)]

  水準方向上,Find距離父view左邊緣預設間隔寬度,之後是FindNext距離Find間隔預設寬度;再之後是寬度不小于20的FindField,它和FindNext以及父view右邊緣的間距都是預設寬度。(豎線“|” 表示superview的邊緣)

  • VFL的使用

  1)使用VFL來建立限制數組方法

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;      

   format :VFL語句

   opts :限制類型

   metrics :VFL語句中用到的具體數值

   views :VFL語句中用到的控件

  2)建立一個字典(内部包含VFL語句中用到的控件)的快捷宏定義

   NSDictionaryOfVariableBindings(...)

   代碼:NSDictionaryOfVariableBindings(v1, v2, v3) 和 [NSDictionary dictionaryWithObjectsAndKeys:v1, @"v1", v2, @"v2", v3, @"v3", nil] 是等價的

  • 代碼:
UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    // 不要将AutoresizingMask轉為Autolayout的限制
    blueView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:blueView];
    
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    // 不要将AutoresizingMask轉為Autolayout的限制
    redView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:redView];
    
    // 間距
    NSNumber *margin = @20;
    
    // 添加水準方向的限制
    NSString *vfl = @"H:|-margin-[blueView]-margin-[redView(==blueView)]-margin-|";
    NSDictionary *views = NSDictionaryOfVariableBindings(blueView, redView);
    NSDictionary *mertrics = NSDictionaryOfVariableBindings(margin);
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:vfl options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:mertrics views:views];
    [self.view addConstraints:constraints];
    
    // 添加豎直方向的間距
    NSNumber *height = @40;
    NSString *vfl2 = @"V:[blueView(height)]-margin-|";
    NSDictionary *mertrics2 = NSDictionaryOfVariableBindings(margin, height);
    NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:vfl2 options:kNilOptions metrics:mertrics2 views:views];
    [self.view addConstraints:constraints2];      

  效果圖如下:

  

【原】iOS學習之蘋果原生代碼實作Autolayout和VFL語言

   VFL存在一定的缺陷,它隻能滿足大部分的限制,不能滿足存在倍數關系的限制!