纯代码ios计算器_iOS 布局进阶:你真的会用 autolayout 么?

前言

iOS 开发发展至今已经相当成熟了。布局的方式从 frame、size、center 到如今强大的 autolayout,将 UI 布局尽量的“自动化”和“智能化”,在很大程度上减少了程序员的工作量。

可能很多人体会过接手一个老项目通篇的 frame 是有多么的痛苦。在现如今的开发中,性能没那么敏感的时候还是提倡使用自动布局(比如 UITableview 的高度自适应用法),以减少大量的 UI 计算。

然而很多开发者可能写出的自动布局一点也不自动。

autolayout 可以理解为:给界面设定规则,让界面随着数据的变化而做出符合规则的变化。

本篇文章重在解决自动布局中复杂的相互约束。

选择布局的工具

在“遥远的”过去,相信大家都用过(或者见别人用过)UIKit 框架的下的 NSLayoutConstraint,用原生的layout 代码体量之大让人有些难以接受,好在大牛们写了一些轮子照福大家,比如业界最有名气的框架—— Masonry。这里就不介绍 Masonry 的基础用法了,相关的文档已经满天飞了。

关于使用 xib、storyboard 还是纯代码布局,大家可以根据开发项目的进度要求和开发者人数来决定,反正他们布局的道理是一样的。

为了直观性,本文使用 xib 来进行描述。

intrinsicContentSize

首先,我们得搞清楚 intrinsicContentSize 是什么。

一个 View 的约束确定需要两个东西,一个是位置,一个是大小。在日常开发中,我们发现给 UILabel、UIImageView、UIButton 实例写约束的时候,只需要给他们位置,而不需要给大小。这是因为它们指定了 intrinsicContentSize(可以理解为内部通过内容计算出了一个合理的大小,我们可以不用指定它)。

指定 intrinsicContentSize 方法:重写 UIView 中的 -(CGSize)intrinsicContentSize: 方法,在需要改变这个值时调用:invalidateIntrinsicContentSize 方法,告知系统值已改变(我们可以自定义指定 intrinsicContentSize 的类)

所以,当我们不给这三种指定了 intrinsicContentSize 的控件的大小的时候,UI 还是不会出错,而且可以通过 intrinsicContentSize 属性获取内部计算过后的大小。

模糊约束

模糊约束,就是 Masonry 中的 lessThanOrEqualTo、greaterThanOrEqualTo,也就是小于等于、大于等于,单独使用模糊约束很简单。

example:

2031b1ecc1a9afd9242704d2daef8c10.png

需求:上图中label宽度和高度遵循 intrinsicContentSize,但是长度不能超过父视图。
实现:Label 距离左边 10,纵向居中,距离右边小于等于 10

优先级

优先级就是在两个约束冲突的时候,优先满足优先级高的约束。

example:

c54f350cb2a9c0f0e551b2ddb9b809c1.png

其实通常情况下的优先级的使用很简单,这里我要讲的是视图的优先级,如下图

870648e6a706b65f63530d180a15f6c6.png

这两个方法相信大家都不陌生(不管有没有用过),他们派上用场的条件是:该视图指定了intrinsicContentSize(固有大小),所以 UILabel、UIImageView、UIButton 都可以配置这几个方法。

当然,这是在nib文件里面进行可视化的配置,在代码里面是这样的(他们是 UIView 的方法):

- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
  • contentHuggingPriority:拒绝变大优先级

  • ContentCompressionResistancePriority:拒绝缩小优先级

换言之,拒绝变大优先级越高,它就不会变大,拒绝缩小优先级越高,它就不会缩小(额,有点废话的感觉)。举个例子见道理:

example:

290eacd5e03cdbc83227dfb282d7dd73.png

需求:A 和 B 相距 10pt,A 的宽度只能和文本一致(A 尽量遵守指定的 intrinsicContentSize)

实现:

step 1:先固定A和B的位置,然后他们相距10,把约束加上过后会报警告

5810e28d0ec0e3f96d072d609b2ba923.png

step 2:我们做以下操作就能解决

056ed1cf6e8e6a1670dcfd35c76b56bc.png

当然,这只是一个默认情况(提醒各位,不光是写业务逻辑,写布局也需要考虑极限情况,这样才能写出完美的布局),当A的文本变化的时候会这样:

0f80f39450409c8b1c5bd200c69b1a98.png

step3:以下的处理就顺理成章了

fd76398761cfa4e3b020a6da77d601ed.png

当然,到目前为止算了完成了需求,但是在实际开发中还有一个问题需要考虑,就是A的内容过长,将B挤压为0了(_)

5d9e5d767c5b93d3f2e682b7d1380756.png

step4:这时候,我们需要给B一个最小的宽度,避免“人间蒸发”,实现这个并没有想象中的那么简单,方法也很多,下面只讲解一种:

94da99a66b66053dbccfffbe05b4c47f.png

6eed319c1f46441ef24bd2a6095e2eaf.png

4e5c3f7dcae94cb28ea7a2026481f5f3.png

12288e6c2aedd9d3924e0bd1621283af.png

结语

布局的重点内容无非就以上讲解的东西,它们单独拎出来时,大家都觉得非常的简单。是否能写出一个完美无 bug 的布局,往往需要结合它们使用(固定约束、模糊约束、优先级),当布局元素很多且极其灵活的时候,才是考研 iOS 工程师布局 UI 能力的时候。

作者:indulge_in
链接:https://www.jianshu.com/p/02a1cd16cc06

本公众号转载内容已尽可能注明出处,如未能核实来源或转发内容图片有权利瑕疵的,请及时联系本公众号进行修改或删除【联系方式QQ : 3442093904  邮箱:support@cocoachina.com】。文章内容为作者独立观点,不代表本公众号立场。版权归原作者所有,如申请授权请联系作者,因文章侵权本公众号不承担任何法律及连带责任。

---END---

f4c5f8aca5064c99b319c9e502f45498.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值