• iOS 自动布局总结


    参考自以下文章:

    http://blog.csdn.net/ysy441088327/article/details/12558097

    http://blog.csdn.net/zhouleizhao/article/details/31741711

    http://blog.csdn.net/dongbaojun_ios/article/details/12566529


    首先介绍自动布局的概念:

    Auto Layout翻译过来意思是自动布局,通过内定的Constraint(约束)和各项条件来计算出合理的布局.而这个合理的布局,符合我们的的预期和意图.

    将我们想象中的结果展现出来.Constraint的设定非常灵活,实现一种布局的方法可以通过多Constraint套来完成.

    下面是在IB中添加自动布局的介绍:

    使用editor中的约束条件:

    这四个是约束条件的设计创建选择框

    下面来逐个介绍:

    1.       Align(校准)


    从上到下依次是:

    左边界-右边界-顶部-底部-中心垂线-中心水平线-底线-中心垂线约束-中心水平线约束

    2.      resolve auto layout issues(决定布局问题)


    这里有两个子框架一个是作用于选中的视图,还有一个是对于全部的视图。

    对于选中的视图: 更新框架-更新约束-添加新的约束-调整成推荐约束-清空约束

    对于全部的视图:是和上面一样的选项,但是不同的是它作用于所有的视图。

    3.       Pin(大头针)


    从上到下这些图标的功能如下:

    固定view自身宽度-固定view自身高度-固定两个view之间的水平空间-固定两个view之间的垂直空间-固定两个view之间的水平空间-固定view与父视图的左边界距离-固定view与父视图的右边界距离-固定view与父视图的上边界距离-固定view与父视图的下边界距离-使两个view自身的宽度相等-使两个view自身的高度相等

    观察一下界面预览右下角,有一排如下图这样的按钮:

    这些功能分别如下图中描述的那样:

    此方法是比较有用的,我们可以使用它来定义约束,而且约束的形式比较自由。当我们面领着4英寸和4.7英寸的大小变化时,我们可以使用采取这个操作:

    在这里可以建立它对于中心线的相对位置,因为中性线的位置是不会变的。




    当然,如果你还用详细的设置一个约束的条件,那么我们应该点击进入详细情况编写。


    二:下面为代码实现自动布局设置

    首先使用第一种设置约束的方式:

    [NSLayoutConstraint constraintWithItem:(id)item
                                 attribute:(NSLayoutAttribute)attribute
                                 relatedBy:(NSLayoutRelation)relation
                                    toItem:(id)otherItem
                                 attribute:(NSLayoutAttribute)otherAttribute
                                multiplier:(CGFloat)multiplier
                                  constant:(CGFloat)constant]
    
    //这个函数的对照公式为:
    //view1.attr1 <relation> view2.attr2 * multiplier + constant
    
    

    函数作用:
    使用了这个函数来为view1添加了一个约束,这个约束是以view2的属性为依据的。
    (注意:如果你想设置的约束里不需要第二个view,要将第四个参数设为nil,第五个参数设为NSLayoutAttributeNotAnAttribute)

    举例:
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:view2
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:10]
    
//翻译过来就是:(view1的左侧)的位置 = (view2的右侧+10个点)的位置
    

    附视图的属性和关系的值:

    typedef NS_ENUM(NSInteger, NSLayoutRelation) {
        NSLayoutRelationLessThanOrEqual = -1,          //小于等于
        NSLayoutRelationEqual = 0,                     //等于
        NSLayoutRelationGreaterThanOrEqual = 1,        //大于等于
    };
    typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
        NSLayoutAttributeLeft = 1,                     //左侧
        NSLayoutAttributeRight,                        //右侧
        NSLayoutAttributeTop,                          //上方
        NSLayoutAttributeBottom,                       //下方
        NSLayoutAttributeLeading,                      //首部
        NSLayoutAttributeTrailing,                     //尾部
        NSLayoutAttributeWidth,                        //宽度
        NSLayoutAttributeHeight,                       //高度
        NSLayoutAttributeCenterX,                      //X轴中心
        NSLayoutAttributeCenterY,                      //Y轴中心
        NSLayoutAttributeBaseline,                     //文本底标线
                                                                                                                                                        
        NSLayoutAttributeNotAnAttribute = 0            //没有属性
    };
    

    注:NSLayoutAttributeLeft/NSLayoutAttributeRight NSLayoutAttributeLeading/NSLayoutAttributeTrailing的区别是left/right永远是指左右,而leading/trailing在某些从右至左习惯的地区会变成,leading是右边,trailing是左边

    使用第二种设置约束的方式:

    NSDictionary *viewsDic = NSDictionaryOfVariableBindings(deleteButton,cancelButton,nextButton);    
    NSArray *constraints = nil;  
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:
      <span style="white-space:pre">	</span>@"H:|-25-[deleteButton(==cancelButton@700)]-(>=8)-[cancelButton(140)]-[nextButton(nextButtonWidth)]-rectY-|"//水平 可视化格式语言  
    <span style="white-space:pre">	</span>options:NSLayoutFormatAlignAllTop //对齐功能  
    <span style="white-space:pre">	</span>metrics:@{@"rectY":@5,@"nextButtonWidth":@30}//指标参数  
    <span style="white-space:pre">	</span>views:viewsDic];//参与约束的对象字典  
    [self.view addConstraints:constraints];  
      
    constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[nextButton]-|" //垂直 可视化格式语言  
    <span style="white-space:pre">	</span>options:0 //无条件  
    <span style="white-space:pre">	</span>metrics:nil//不带指标参数  
    <span style="white-space:pre">	</span>views:viewsDic];//参与约束的对象字典    
    [self.view addConstraints:constraints];
    

    函数介绍:

    关于constraintsWithVisualFormat:函数介绍:

    constraintsWithVisualFormat:参数为NSString型,指定Contsraint的属性,是垂直方向的限定还是水平方向的限定,参数定义一般如下:

    V:|-(>=XXX):表示垂直方向上相对于SuperView大于、等于、小于某个距离

    若是要定义水平方向,则将V:改成H:即可

    在接着后面-[]中括号里面对当前的View/控件的高度/宽度进行设定;

    options:字典类型的值;这里的值一般在系统定义的一个enum里面选取

    metricsnil;一般为nil,参数类型为NSDictionary,从外部传入 //衡量标准

    views:就是上面所加入到NSDictionary中的绑定的View

    在这里要注意的是AddConstraints   AddConstraint之间的区别,一个添加的参数是NSArray,一个是NSLayoutConstraint

    使用规则

     

    |: 表示父视图

      -:表示距离

      V:  :表示垂直

      H:  :表示水平

    >= :表示视图间距、宽度和高度必须大于或等于某个值

       <= :表示视图间距、宽度和高度必须小宇或等于某个值

       == :表示视图间距、宽度或者高度必须等于某个值

    @  :>=<===  限制   最大为  1000


    下面是一个使用代码来实现界面约束的代码实例:

    if(floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1)
        {
            self.edgesForExtendedLayout = UIRectEdgeNone;
        }
        
        //自动布局
        //正常的创建按钮,但不用设置按钮的Frame属性
        UIButton * leftButton = [UIButton buttonWithType:UIButtonTypeSystem];
        leftButton.layer.borderWidth = 2.0;
        leftButton.layer.borderColor = [UIColor blackColor].CGColor;
        [leftButton setTitle:@"左" forState:UIControlStateNormal];
        [self.view addSubview:leftButton];
        
        UIButton * rightButton = [UIButton buttonWithType:UIButtonTypeSystem];
        rightButton.layer.borderWidth = 2.0;
        rightButton.layer.borderColor = [UIColor blackColor].CGColor;
        [rightButton setTitle:@"右" forState:UIControlStateNormal];
        [self.view addSubview:rightButton];
        
        //将自适应向布局约束的转化关掉(根据情况有时需要有时不需要)
        [leftButton setTranslatesAutoresizingMaskIntoConstraints:NO];
        [rightButton setTranslatesAutoresizingMaskIntoConstraints:NO];
        
        //创建一个存放约束的数组
        NSMutableArray * tempConstraints = [NSMutableArray array];
        
        /*
         创建水平方向的约束:在水平方向,leftButton距离父视图左侧的距离为80,leftButton宽度为60,rightButton和leftButton之间的距离为30,rightButton宽60
         */
        [tempConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-80-[leftButton(==60)]-30-[rightButton(==60)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(leftButton,rightButton)]];
        
        /*
         创建竖直方向的约束:在竖直方向上,leftButton距离父视图顶部30,leftButton高度30
         */
        [tempConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[leftButton(==30)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(leftButton)]];
        /*
         竖直方向的约束:在竖直方向上,rightButton距离其父视图顶部30,高度与leftButton的高度相同
         */
        [tempConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[rightButton(==leftButton)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(rightButton,leftButton)]];
        
        //给视图添加约束
        [self.view addConstraints:tempConstraints];
    

    Layout Process(自动布局过程介绍)

    与使用springs and struts(autoresizingMask)比较,Auto layout在view显示之前,多引入了两个步骤:updating constraints 和laying out views。每一个步骤都依赖于上一个。display依赖layout,而layout依赖updating constraints。 updating constraints->layout->display


    第一步:updating constraints,被称为测量阶段,其从下向上(from subview to super view),为下一步layout准备信息。可以通过调用方法 setNeedUpdateConstraints 去触发此步。constraints的改变也会自动的触发此步。但是,当你自定义view的时候,如果一些改变可能会影响到布局的时候,通常需要自己去通知Auto layout。说到自定义view了,通常可以重写updateConstraints方法,在其中可以添加view需要的局部的contraints。


    第二步:layout,其从上向下(from super view to subview),此步主要应用上一步的信息去设置view的center和bounds。可以通过调用setNeedsLayout去触发此步骤,此方法不会立即应用layout。如果想要系统立即的更新layout,可以调用layoutIfNeeded。另外,自定义view可以重写方法layoutSubViews来在layout的工程中得到更多的控制。


    第三步:display,此步时把view渲染到屏幕上,它与你是否使用Auto layout无关,其操作是从上向下(from super view to subview),通过调用setNeedsDisplay触发,


    因为每一步都依赖前一步,因此一个display可能会触发layout,当有任何layout没有被处理的时候,同理,layout可能会触发updating constraints,当constraint system更新改变的时候。


    需要注意的是,这三步不是单向的,constraint-based layout是一个迭代的过程,layout过程中,可能去改变constraints,有一次触发updating constraints,进行一轮layout过程。这可以被用来创建高级的自定义视图布局,但是如果你每一次调用自定义layoutSubviews都会导致另一个布局传递,那么你将会陷入一个无限循环中。如图:


    setNeedsLayout和layoutIfNeeded方法介绍

    - (void)setNeedsLayout
    此方法会将view当前的layout设置为无效的,并在下一个upadte cycle里去触发layout更新。
    
    - (void)layoutIfNeeded
    使用此方法强制立即进行layout,从当前view开始,此方法会遍历整个view层次(包括superviews)请求layout。因此,调用此方法会强制整个view层次布局。



  • 相关阅读:
    20155229-付钰涵-分析自我技能延展到c语言学习状况
    预备作业①
    读《嵌入式系统项目分析入门与实践》⑤
    读《嵌入式系统项目分析入门与实践》④
    读《嵌入式系统项目分析入门与实践》③
    读《嵌入式系统项目分析入门与实践》②
    读《嵌入式系统项目分析入门与实践》①
    读《大学有感》④
    读《大学之路》有感③
    读《大学之路》有感②
  • 原文地址:https://www.cnblogs.com/AbeDay/p/5026961.html
Copyright © 2020-2023  润新知