zoukankan      html  css  js  c++  java
  • 【原】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];

      效果图如下:

      

       VFL存在一定的缺陷,它只能满足大部分的约束,不能满足存在倍数关系的约束!

  • 相关阅读:
    《Apache Doris在美团外卖数仓中的应用实践》
    《一文教会你如何写复杂业务的代码》
    《SOFA企业应用框架》
    《为什么阿里巴巴代码规约要求避免使用 Apache BeanUtils 进行属性的拷贝》
    《浅析VO、DTO、DO、PO的概念、区别和用处》
    Spring 注解
    《浅析VO、DTO、DO、PO的概念、区别和用处》
    dsgn_ebook
    《清华大学刘世霞“可解释机器学习的可视化分析”(附PPT)》
    《图结构的相似度度量与分类》
  • 原文地址:https://www.cnblogs.com/gfxxbk/p/5811579.html
Copyright © 2011-2022 走看看