iOS9 Programming - Layout (Autoresizing)

在日常开发中我们经常会看到,当superview的bounds发生变化的时候,他的subview也会随之移动,但这是为什么呢?在superview的size发生变化的时候,subview内部发生了什么呢?看似简单的现象中其实包含了很多知识,估计再接下来很长的时间里我将仔细梳理关于Layout方面的知识,若大家在阅读过程中发现什么问题请及时纠正,共同进步😄


说起 layout 其实我们在开发过程中无时不刻不在用,特别是在写界面的时候,比如适配不同的设备大小,横屏竖屏转换的时候界面不能乱,有些 app 需要适配 iphone 和 ipad 两种设配的不同尺寸,还有tableview cell的内容自适应,有些时候当隐藏导航栏和现实导航栏的时候界面可能会伸缩或拉长等等,所以说 layout 在我们写界面是很有用的,因此他真的很重要。
Layout 有三种主要的表现形式。分别是:

  1. Manual Layout(手动布局):当 superview 的大小发生变化的时候,会接受到一个 layoutSubviews 的信息, 之后你通过重写 layoutSubviews 方法来手动的重新为 subviews 布局,很明显这将会导致很大的工作量
  2. Autoresizing(自动调整尺寸):这种方式是 iOS6 之前的一种自动布局方式。当 superview 的大小改变时,subview 会通过 autoresizingMask 属性来调整值。这个会在后面讲到
  3. Autolayout(自动布局):它是在 iOS6 引进的, 主要通过 view 的 constraint 来实现的。 一个 constraint 其实就是一个 NSLayoutConstraint 实例对象,通过数字来描述一个 view 相对于其他view 的大小和位置。这比autoresizeingMask 更精密更容易理解,一个 view 可以有多个 constraint, 并且他们可以描述任意两个 view 之间的关系。其实 auotolayout 在背后帮你实现了 layoutSubviews 方法, 你可以不用手写代码来实现很多复杂的约束。

你的 lauout 可以使用以上三种的任何一个或多个的组合,但一般来说我们很少会用手动布局,因为工作量大且效率较低。AutoresizeSubviews 默认会自动开启,除非你设置 superview 的 autoresizesSubviews 属性为 false,或者你使用了autolayout 则AutoresizeSubviews 将会被禁用。Autolayout 可以用在任何你想用的地方,是不是很方便呀。需要注意的是,在 Xcode7 及 7以后的版本中,autolayout 会在 xib或者 storyboard 中默认勾选, 如果没有勾选的话则会使用 autoresizng 而不是 autolayout 哟!

Autoresizing

Autoresizing 主要是通过设置 subview 的 springstruts属性来实现的。Spring 可以被拉伸,但是 strut 不可以,Spring 和 struts 可以在外部或内部,水平或垂直方向指定,因此你可以通过这两个属性来指定一个view要如何调整大小护着调整位置。
试想一下,一个 view 在他的 super的中心位置,当父视图调整大小时,view也会跟着调整大小。view 将会在其外部是固定(struts)的在内部是弹性(spring)的
继续设想有一个view在他的 superview 的中心位置,但是 view 不随父视图大小的变化而变化,这时view将会在外部 spring 内部 structs
再设想有一个OK按钮在他父视图的右下角位置,则 view 在内部是 struts,在他右方和下方是外部 struts,在上方和左方则是外部 spring。
最后设想有一个 textfield 在其 superview 的顶部,并且与 superview 同宽,这时他的外部是 struts, 但是下边是 spring, 谁知方向时内部 struts 竖直方向内部 spring
对于上面所讲到的几种情况大家可以先画图理解一下。

在代码中springstruts 是通过的 view 的 autoresizingMask 属性来设置的。autoresizingMask 中的 options 是位掩码, 这些位掩码是在定义在一个 struckt 里面,这些位掩码表明了哪些是需要 spring 的,也就是说,没有专门设置 struts 的选项,只要没有设置,就是 struts 的。默认值是.None,也就意味着,所有的方向都是 struts,但是这是不可能的,当 superview 改变的时候,subview 肯定会改变,所以,.None 并不是所有都是 struts ,而是 .FlexibleRightMargin 和 .FlexibleBottomMargin 。


下面我门来举个例子,理解一下Autoresizing

 let v1 = UIView(frame: CGRectMake(100,111,132,194))
        v1.backgroundColor = UIColor.magentaColor()
        let v2 = UIView(frame: CGRectMake(0,0,132,10))
        v2.backgroundColor = UIColor.greenColor()  
        let v3 = UIView(frame: CGRectMake(v1.bounds.width-20, v1.bounds.height-20,20,20))
        v3.backgroundColor = UIColor.redColor()
        self.view.addSubview(v1)
        v1.addSubview(v2)
        v1.addSubview(v3)

运行一下你将会看到下图界面:

Autoresizeing 01.png

接下来我们为 v2 和 v3 分别添加 spring 和 struct 让他们看起来好像一个 textfild 在界面顶部, 一个 ok 按钮在界面的右下角

v2.autoresizingMask = .FlexibleWidth
v3.autoresizingMask = [.FlexibleTopMargin, .FlexibleLeftMargin]
v1.bounds.size.width += 40
v1.bounds.size.height -= 50

运行结果如下图:

Autoresizing 02.png

上面这个例子可以看得出来 autoresizing 都做了哪些事情, 不过还是有点人为的改变superview的大小,在日常开发过程中 superview的大小变化通常都是自动的,不受人为控制,比如旋转屏幕到横屏状态,接下来我们通过改变v1的frame来达到想要的效果

v1.frame = self.view.bounds
v1.autoresizingMask = [.FlexibleHeight, .FlexibleWidth];

运行一下可以看到,v1充满了整个屏幕

Autoresizing 03.png

我们再旋转一下屏幕可以看到

Autoresizing 04.png

现在是横屏状态但 view 的布局并没有错乱,还是在正确的位置上

现在我们可以看出采用 autoresizing 布局还是蛮简单的,也正是因为他太过简单只能用来描述 superview 和 subview 之间的位置关系,无法描述view 与 view 之间的关系。在有 autolayout 之前,如果要使用 auto resizing 来实现比较复杂的布局还需要介入手动布局,调用 layoutsubviews 方法,这种方式一方面比较麻烦,另一方面还容易出错。所以还是让我们好啊后来研究一下 Autolayout 吧!看看它带给我们哪些便利!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容