zoukankan      html  css  js  c++  java
  • 【转】iOS学习之Autolayout(代码添加约束) -- 不错不错

    原文网址:http://www.cnblogs.com/HypeCheng/articles/4192154.html

    DECEMBER 07, 2013

    学习资料

    文章

    前两篇文章对如何在xcode 5中使用autolayout讲得已经很详细了。我使用了一段时间autolayout的感觉是,一般情况下都可以通过xcode的ib上直接设置autolayout的各种属性完成项目需求,除非遇到需求比较复杂的布局。

    官方的Auto Layout Guide讲得详细易懂,推荐

    WWDC视频

    2012

    2013

    一些学习到的知识点整理

    用代码创建一个 NSLayoutConstraint

    下面的方法遵循一个计算公式:

    view1.attribute1 = multiplier × view2.attribute2 + constant

    1
    2
    3
    4
    5
    6
    7
    
    + (id)constraintWithItem:(id)view1
                     attribute:(NSLayoutAttribute)attribute1
                     relatedBy:(NSLayoutRelation)relation
                      toItem:(id)view2
                   attribute:(NSLayoutAttribute)attribute2
                  multiplier:(CGFloat)multiplier
                    constant:(CGFloat)constant;
    

    例子:

    • Button.centerX = Superview.centerX
    1
    2
    3
    4
    5
    6
    7
    
    [NSLayoutConstraint constraintWithItem:button
                               attribute:NSLayoutAttributeCenterX
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeCenterX
                                multiplier:1.0f
                                  constant:0]
    
    • Button.bottom = Superview.bottom - 
    1
    2
    3
    4
    5
    6
    7
    
    [NSLayoutConstraint constraintWithItem:button
                               attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0f
                                  constant:-padding]
    

    创建完 NSLayoutConstraint 接下来要将它添加到 view 里,添加方法很简单,用 view 的- (void)addConstraint:(NSLayoutConstraint *)constraint添加。但是应该添加到哪个 view 里呢?

    1. 兄弟 view 的 Constraint 添加到他们的 superview

      兄弟 view 之间添加 Constraint 到 superview

    2. 两个 view 的父 view 是兄弟关系的,Constraint 添加到父 view 的 superview 上

      父 view 是兄弟关系的,Constraint 添加到父 view 的 superview 上

    3. 如果两个 view 是 parent-child 关系,Constraint 添加到 parent view上

      如果两个 view 是 parent-child 关系,Constraint 添加到 parent view上

    跨层级 view 之间的 Constraint

    有如下的视图层级:

    - View
        - UIScrollView
            - UISwitch
        - UIButton
    

    其中UISwitch相对 UIScrollView 水平居中,和 ScrollView 同一层级有一个 UIButton,现在要始终保持 UIButton 的水平中点位置和 UISwitch 的水平中点位置在同一条线上。

    为 UISwitch 的水平居中 Constraint 建立一个 IBOutlet。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
     - (void)viewDidLoad {
          [super viewDidLoad];
          // Remove the IB-generated constraint centering the switch in its super view
          [self.scrollView removeConstraint:self.horizontalSwitchConstraint]
      
          // Add a new constraint centering the switch on the button
          NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:self.switchButton
                                                              attribute:NSLayoutAttributeCenterX
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:self.button
                                                              attribute:NSLayoutAttributeCenterX
                                                             multiplier:1.0f
                                                               constant:0];
          [self.view addConstraint:cn]; 
      }
    

    上面的的代码就实现了跨层级视图之间的 Constraint 设置。其实就是这么简单

    设置Autolayout有两个原则

    • Ambiguous Layout(The constraints must be suficient)
    • Unsatisfiable Constraints(The constraints must not conflict)

    在 IB 中设置明确的宽度

    设置宽度有几个原则:

    • 如果一个 View 的宽高在显示的时候是不确定的:让 view 根据内容改变大小(size to fit size)
    • 如果一个 View 有确定的大小:改变其宽度的 Constraint Relation 为 >=
    • 正确的设置Content Hugging Priority(内容压缩优先级) 与 Content Compression Resistance Priority(内容抗压缩优先级)

    Relation(Greater/Less) 与 Priority

    Greater/Less 一般与 Priority 一起使用,为一个 Constraint 设置了 Greater/Less 后,调整 Priority。如果 Constraint 的 Priority 的值越大,程序优先设置它的 Constraint 效果。

    如果两个 View 不在同一个层级,此时想要设置他们之间的 Constraint,只能通过代码实现。简单的方式是:先在 Xcode 中设置了 Constraint,然后为这个 Constraint 建立一个 IBOutlet,回到代码中,移除想要替换的 Constraint。

    Content Hugging Priority 与 Content Compression Resistance Priority

    含义:

    • Content Hugging Priority(内容压缩优先级)
    • Content Compression Resistance Priority(内容抗压缩优先级)。

    如果 Constraint 发生冲突时,会先找优先级高的UIView,满足优先级高的UIView 的Constraint 后再依次找优先级低的 Constraint 满足,最后改变 View 的 Frame。如果发生多个 Constraint不能同时满足的情况,就发生了Unsatisfiable Constraints的错误。

    Visual Format Language

    VFL(Visual Format Language),提供了一种让代码以一种可视化的方式来设置不同 views 之间的 Constraint。

    1
    2
    3
    4
    5
    
     [NSLayoutConstraint constraintsWithVisualFormat:@"[cancelButton]-[acceptButton]"] options:0 metrics:nil views:viewsDictionary];
      
      UIButton *cancelButton = ...
      UIButton *acceptButton = ...
      viewsDictionary = NSDictionaryOfVariableBindings(cancelButton, acceptButton);
    

    Examples:

    Property Examples
    Inequality,Priority  [wideView(>=60@700)]
    Vertical:Flush Views,Equal Heights  V:[redBox][yellowBox(==redBox)]
    Combination  H:|-[Find]-[FindNext]-[FindField(>=20)]-

    Inequality,PriorityVertical:Flush Views,Equal Heights Combination

    Constraint 在什么时候更新

    autolayout_phases_of_display

    UIView中

    -setNeesdDisplay
    -setNeedsLayout
    -setNeedsUpdateConstraints
    

    UIView/UIWindow中

    -layoutIfNeeded
    

    关于 intrinsicContentSize

    在 UIView 中有个方法-intrinsicContentSize,用于指定一个 view 的 width 和 height,设置了-intrinsicContentSize相当于设置一个不可变的长度或者宽度。有点像 UISlider 只能设置宽度,不能设置高度那样。

    Debug

    1. 在 Xcode 中,设置 Autolayout 时可能出现3种状态,分别会出现黄色、红色、蓝色的线或线框。

      • 出现黄色的线或者线框表示:View 根据设置的 Constraints 最后计算出的 frame 位置和在xib 中 view 目前显示的位置不一致。此时并没有错误,只要更新一下 Update frames 以下就好
      • 出现红色的线或者线框表示:出现了Ambiguous Layout(Constraints 太少以至不能确定一个 view 的位置)或者Unsatisfiable Constraints(Constraints 有冲突,确定 view 一个方向上的 Constraints 超过1个)。这种情况要找到没有正确设置 Constraints 的 View 添加缺失的 Constraints 或者删除多余的 Constraints。
      • 蓝色线条或者线框表示这个 view 的 Constraints 正确设置,并且 view 目前显示的位置和 Constraints 计算得出的最终位置是在同一个地方。
    2. 在代码添加 Constraints 的 Debug 方法。

      • 在控制台输出AutolayoutTrace:po [[UIWindow keyWindow] _autolayoutTrace]。如果此时有Ambiguous LayoutUnsatisfiable Constraints,可以在输出的代码中看到。
    3. 有用的 debugging defaults

      • 双倍的国际化字符串:NSDoubleLocalizedStrings YES
      • 显示视图的对齐框: UIViewShowAlignmentRects YES

    AutoresizingMask自动转化成 Constraint

    view有一个 translatesAutoresizingMaskIntoConstraints 属性,如果设置为 NO,那么在运行时,程序不会自动将AutoresizingMask转化成 Constraint。

    Animation

    关键是在 UIView Animation 中调用[view layoutIfNeeded]

    1
    2
    3
    4
    5
    6
    
     
    [UIview animateWithDuration:1.0 animations:^{
      // Constraint Changed...
      
      [view layoutIfNeeded];
    }];
    

    Github上一些好用的Autolayout第三方库

    iOS UITextView 输入内容实时更新 cell 的高度

    这篇文章介绍了在一个动态数据的 table view 中,cell 根据 text view 内容的输入实时改变 cell 和 table view 的高度。自动计算 cell 高度的功能使用 iOS 8 才支持的自适应 cell,如果你还不知道 iOS 8 自适应 cell, …… Continue reading

    iOS 8 自适应 Cell

    Published on November 13, 2014
  • 相关阅读:
    Java中如何动态创建接口的实现
    使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
    MyBatis中的@Mapper注解及配套注解使用详解(上)
    SpringMVC-DispatcherServlet工作流程及web.xml配置
    SpringMVC-DispatcherServlet配置(Spring-servlet.xml)
    Spring MVC 配置文件dispatcher-servlet.xml 文件详解
    python3 UnicodeEncodeError: 'gbk' codec can't encode character 'xa0' in position 30: illegal multibyte sequence
    python3之日期和时间(转载)
    python3 操作sqlSever
    python 抓取alexa数据
  • 原文地址:https://www.cnblogs.com/wi100sh/p/5626044.html
Copyright © 2011-2022 走看看