美文网首页iosios 开发IT圈
窥探iOS可视化编程中AutoLayout的精髓

窥探iOS可视化编程中AutoLayout的精髓

作者: VCC | 来源:发表于2016-03-22 00:19 被阅读2197次

    在iOS开发中,使用可视化编程能够简单快速的拖拽出令人满意的UI。但是,除了简单的拖拽之外,还有一项工作对于可视化编程来讲必不可少,那就是AutoLayout自适应布局。因为,没有进行AutoLayout的UI将无法适应屏幕大小不同的机型。本文主要基于Xcode 7.2.1总结一下个人在可视化编程中进行AutoLayout的几点经验,大神请绕过。

    本文结构图

    一、关于约束

    在可视化编程中进行AutoLayout的方法就是添加约束。通过添加合适的约束,使控件能够按照预期的位置和大小显示在屏幕大小不同的机型上,也就实现了AutoLayout自适应布局。

    1、添加约束

    学习过可视化编程的小猿们应该都知道添加约束的几种主要方法:

    方法一:使用 Interface Builder 界面右下角的 Stack 、Align 、Pin 、Resolve Auto Layout Issues 四个约束操作按钮。

    方法二:在 Interface Builder 界面上,按住 control 键,从控件开始拖动鼠标到参考控件上,松开鼠标就会弹出约束选择窗口(如图 1-1)。

    图 1-1

    方法三:在 Interface Builder 界面左侧的 Document Outline 窗口中,按住 control 键,从控件开始拖动鼠标到参考控件上,松开鼠标就会弹出约束选择窗口(如图 1-2)。

    图 1-2

    2、约束分类

    从上面的截图中我们可以发现,约束大致上可以分为三类:

    2.1  距离约束

    距离约束主要用于限定控件相对于参考控件的距离关系。相对于不同的参考控件,距离约束的具体名称会有一些区别,但作用效果基本相同。例如:

    相对于根 View 的距离约束为:Leading Space to Container Margin 、Trailing Space to Container Margin 、Vertical Spacing to Top Layout Guide 、Vertical Spacing to Bottom Layout Guide 。

    相对于非根 View 的父 View 的距离约束为:Top Space to Container 、Leading Space to Container 、Bottom Space to Container 、Trailing Space to Container 。

    相对于无包含关系的其它控件的距离约束为:Horizontal Spacing 、Vertical Spacing 。

    2.2  对齐约束

    对齐约束主要用于限定控件相对于参考控件的距离关系。同样,相对于不同的参考控件,对齐约束的具体名称也会有一些区别。例如:

    相对于跟 View 或父 View 的对齐约束为:Center Horizontally in Container 、Center Vertically in Container 。

    相对于无包含关系的其它控件的对齐约束为:Center Horizontally 、Center Vertically 。

    2.3  宽高约束

    宽高约束主要用于限定控件相对于参考控件的宽高关系,包括:Equal Widths 、Equal Heights 、Aspect Ratio 。

    二、窥探精髓

    上面讲述了关于约束的基本内容,但具有可视化编程经验的小猿们都清楚,只知道这些基本内容还远不足以添加出能够满足各种 AutoLayout 需求的约束。所以说,接下来我们就深入其中,窥探精髓。

    在 Interface Builder 界面中选中某个控件,我们就可以在 右侧 Utilities 窗口 —> Size 选项卡 —> Constraints 选项 下查看已经添加的约束(如图 2-1),并可以点击 Edit 或者双击进入约束详情对这些约束进行编辑。

    图 2-1

    或者我们可以直接在 Interface Builder 界面选中控件上的具体约束,在 右侧 Utilities 窗口 —> Size 选项卡 下就会显示约束详情(如图 2-2),可直接进行编辑。

    图 2-2

    约束详情中都包括哪些内容呢?下面我们就来详细了解一下。

    在图 2-2 中我们可以看到,约束详情的最上面是约束的名称,也就是图中的 Center X Alignment Constraint ;最下面是一个 Placeholder 选项,内容是 Remove at build time ,从字面意思就可以知道,如果选择了这个选项,编译时将会移除这个约束,所以说一般情况下我们是不会勾选这个选项的;详情中剩余的内容也就是需要重点讲述的内容,其实这些内容都可以用 NSLayoutConstraint 的属性进行描述:

    First Item:(id firstItem 属性).(NSLayoutAttribute firstAttribute 属性),其中的 firstAttribute 属性是可选的。

    Relation:NSLayoutRelation relation 属性,有三个选项可供选择:Less Than or Equal(<=)、Equal(=)以及 Greater Than or Equal(>=),默认是 Equal(=)。

    Second Item:(id secondItem 属性).(NSLayoutAttribute secondAttribute 属性),其中的 secondAttribute 属性是可选的。

    Constant:CGFloat constant 属性,常数,可以手动输入,用以对约束进行调整。

    Priority:UILayoutPriority priority 属性,优先级,默认值为1000,可以手动输入,一般不做修改。

    Multiplier:CGFloat multiplier 属性,系数,可以手动输入,用以对约束进行调整。

    Identifier:NSString *identifier 属性,约束标识。

    这些内容遵循一个公式来限定约束:

    First Item =(<=、>=) Multiplier × Second Item + Constant

    这个公式就是约束的精髓,也就是可视化编程 AutoLayout 的精髓。公式中 First Item 的 firstAttribute 属性和 Second Item 的 secondAttribute 属性是可选的,Multiplier 系数和 Constant 常数可以手动输入,所以说我们可以通过编辑约束来随心所欲的修改约束,进而限定控件的位置和大小,实现可视化编程中的各种 AutoLayout 需求。

    三、特殊需求

    1、Label 的高度自适应

    Label 的高度自适应非常简单。具有可视化编程经验的小猿们都知道,给 Label 加约束时不添加宽高约束也不会报错,因为系统默认 Label 的 numberOfLines = 1,height = 20.5,宽度根据文字长短自适应。但有些时候,我们需要使用 Label 显示一段很长的文本,就需要进行高度自适应:添加约束限定 Label 宽度,在 右侧 Utilities 窗口 —> Attributes 选项卡 —> Label 选项 下将 Lines 设置为0。

    2、ScrollView 的 AutoLayout

    曾经尝试过在可视化编程中对 ScrollView 进行 AutoLayout 的小猿们都知道,如果我们以 ScrollView 作为参考控件给其上的控件添加宽高约束,系统就会报错。怎么办呢?曾经有朋友告诉过我一个使用三方解决的方法,具体是什么三方我不记得了,因为我基本不会用这种方法。

    那么我是怎么解决的呢?其实只要清楚问题的根源,我们就可以很简单的解决它。

    我们使用代码创建 ScrollView 的时候,都必须要给定它的 contentSize 属性,但是我们在可视化编程时并没有对这一属性进行设置。所以,当我们以 ScrollView 作为参考控件给其上的控件添加宽高约束时,系统自然就会报错。解决问题办法也就是在给 ScrollView 上的控件添加宽高约束时以除 ScrollView 以外的其它控件作为参考控件。

    考虑到我们可能会在 ScrollView 上添加很多个控件,最好的作法就是先在 ScrollView 上添加一个空白 View 作为 contentView ,添加好约束后将需要添加的控件添加到 contentView 上,这时就可以按照正常添加约束的方法给这些控件添加约束了。下面的动画演示的是在 ScrollView 上添加一个与根 View 等宽、高度为根 View 高度2倍的 contentView ,并添加约束的过程:

    图 3-1

    3、TableViewCell 的高度自适应

    在实际开发中可能经常会遇到 Cell 的高度要根据显示的文字的多少进行调整的需求,这种情况下,如果我们通过可视化编程来定制 customCell ,又该怎样添加约束来使 customCell 的高度能够自适应呢?

    首先,我们要给 customCell 中显示文字的 Label 添加约束:

    第一步:限定 Label 的宽度,但不要限定 Label 的高度,因为 Label 高度自适应之后 customCell 才能高度自适应;

    第二步:通过 Leading Space 或 Trailing Space 或 Center.X 限定 Label 在水平方向上的位置;

    第三步:限定 Label 的 Top Space 和 Bottom Space 两个距离约束;

    第四步:在 右侧 Utilities 窗口 —> Attributes 选项卡 —> Label 选项 下将 Lines 设置为0。

    然后,我们要在代码中设置 TableView 的 estimatedRowHeight 和 rowHeight 属性:

    self.tableView.estimatedRowHeight = 30 ;     // 设置 customCell 的估计高度

    self.tableView.rowHeight = UITableViewAutomaticDimension;     // 设置 customCell 自适应高度

    这样,我们就实现了 TableViewCell 的高度自适应。

    四、实例演示

    接下来根据实际开发中的一个 AutoLayout 需求,来给大家做一个小小的演示。之前一个朋友给提了一个 AutoLayout 的需求,具体的 UI 效果如图 4-1,要求三个 ImageView 等宽等高,之间的两个间隔和屏幕边缘的两个间隔宽度相等。朋友告诉我说他是在四个间隔区域使用了四个空白的占位 View ,然后再添加如下约束:

    1、添加距离约束:限定两边的空白 View 与屏幕边缘的距离为0,限定四个占位 View 与三个 ImageView 两两之间的距离为0;

    2、添加对齐约束:限定四个占位 View 和三个 ImageView 相对于根 View 竖直居中;

    3、添加宽高约束:限定四个占位 View 和三个 ImageView 的高度均为 0.2 × 屏幕高度,限定四个占位 View 的宽度均为 0.07 × 屏幕宽度,限定三个 ImageView 的宽度均为 0.24 × 屏幕宽度。

    图 4-1

    如果试着把这些约束添加一遍,就会发现这种方法非常麻烦,还容易出错。但是,这篇文章读到这里,我们已经完全没必要再使用这种浪费空白占位 View 又非常麻烦的方法了。我们完全可以只对三个 ImageView 添加约束来实现图 4-1中的 UI 效果。计算 Multiplier 系数的过程请自行脑补,下面只演示添加约束的过程:

    图 4-2

    Notes:

    1、衷于分享,欢迎转载;

    2、博主才疏学浅,敬请批评指正;

    3、如果对您有所帮助,我倍感荣幸,也请您点个赞。

    相关文章

      网友评论

      • 492647699e8d:有没有试过 针对于Xib 嵌套使用情况下的 约束使用情况呢?
        492647699e8d:@VCC 加个好友聊吧 我Q432591
        VCC:@如此简单 没太懂你的意思,能具体描述一下你的需求吗?
      • 大学霸: 您好,那个滚动式图的添加的contentview如果我在contentview上加了个label,高度不确定,之后contentview高度怎么设置。
        VCC:你先不要给 contentView 添加高度约束,先把需要的控件添加到 contentView 上,这些控件的高度不能依赖 contentView 的高度,可以依赖 ScrollView 的父视图,所有控件都添加完并添加好约束之后,通过最下面一个控件的 bottom 约束 contentView 的高度。
        大学霸:@VCC :joy: :joy: :joy: 我尝试了无法解决呢
        VCC:我理解您的意思是在一个 ScrollView 上,有很多控件,然后里面有高度不确定的 Label,不知道您是不是这个意思?如果是这样的话,很高兴的告诉你,是可以实现的哦,不过文字表达起来比较复杂😂😂😂
      • 申经炳Ewane:感谢博主:sunglasses:

      本文标题:窥探iOS可视化编程中AutoLayout的精髓

      本文链接:https://www.haomeiwen.com/subject/asxklttx.html