如何将AutoLayout和ScrollView很好地融合在一起

前因

据Nic说现场是大便,陈坤是马桶,所以能很好地融合在一起。

然而在日常的开发工作中,我们遇到AutoLayout和ScrollView,未必就能将它们很好地融合在一起。

今天Q群里也有朋友在踩AutoLayout和ScrollView的坑,过程中两者融合得不是很好,于是便在群里声泪俱下。为了让这类惨剧少那么一点天空蓝那么一点。

Demo

I'm Demo Address

后果

为了让这类惨剧少那么一点天空蓝那么一点。Demo地址已经在上面了,我分别用StoryBoard和代码(我使用的是PureLayout)示范了一个例子。

完成后的界面是这样的:


图是HOCC拿新秀大赛冠军时候梅姐颁奖的现场
这首歌很好听,欢迎听XD

其中代码的实现也很简单,一并附上。示例中将写约束的方法写在Controller里并不是最佳实践,实际应用时请自行封装(逃(并非凑字数XD

import UIKit

class HOCCCodeController: UIViewController {

    var didSetupConstraints = false

    let scrollView = UIScrollView.newAutoLayoutView()
    
    let container = UIView.newAutoLayoutView()
    
    // MARK: Container Subviews
    let imageView: UIImageView = {
        let imageView = UIImageView.newAutoLayoutView()
        imageView.contentMode = .ScaleAspectFit
        imageView.image = UIImage(named: "hocc")
        return imageView
    }()
    
    ...     
    ...
    

// MARK: LifeCircle
extension HOCCCodeController {
    override func loadView() {
        // Add Subviews
        view = UIView()
        view.backgroundColor = .whiteColor()
        view.addSubview(scrollView)
        
        scrollView.addSubview(container)
        
        let subviews = [imageView, songNameLabel, singerLabel, contentView, lyricLabel]
        for subview in subviews {
            container.addSubview(subview)
        }
        
        contentView.addSubview(lyricistLabel)
        contentView.addSubview(composerLabel)
        
        // Trigger
        view.setNeedsUpdateConstraints()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "Code"
    }
}

// MARK: UpdateViewConstraints
extension HOCCCodeController {
    override func updateViewConstraints() {
        if !didSetupConstraints {
            
            // 1. Setup ScrollView constraints
            scrollView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero)
            
            // 2. Setup Container constraints
            container.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero)
                /* It is the Key */
            container.autoMatchDimension(.Width, toDimension: .Width, ofView: scrollView)
            
            imageView.autoAlignAxisToSuperviewAxis(.Vertical)
            imageView.autoPinEdgeToSuperviewEdge(.Top, withInset: 30)
            imageView.autoMatchDimension(.Width, toDimension: .Width, ofView: container, withMultiplier: 0.7)
            if let image = imageView.image {
                let ratio = image.size.height / image.size.width
                imageView.autoMatchDimension(.Height, toDimension: .Width, ofView: imageView, withMultiplier: ratio)
            }
            
            let views = [songNameLabel, singerLabel, contentView, lyricLabel]
            
            var previousView: UIView?
            for view in views {
                view.autoAlignAxisToSuperviewAxis(.Vertical)
                if let previousView = previousView {
                    view.autoPinEdge(.Top, toEdge: .Bottom, ofView: previousView, withOffset: 15)
                } else {
                    view.autoPinEdge(.Top, toEdge: .Bottom, ofView: imageView, withOffset: 30)
                }
                previousView = view
            }

            lyricLabel.autoSetDimension(.Width, toSize: 230)
            lyricLabel.autoPinEdgeToSuperviewEdge(.Bottom, withInset: 80)
            
            // 3. Setup ContentView constraints
            lyricistLabel.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsZero, excludingEdge: .Right)
            composerLabel.autoPinEdge(.Leading, toEdge: .Trailing, ofView: lyricistLabel, withOffset: 50)
            composerLabel.autoAlignAxis(.Horizontal, toSameAxisOfView: lyricistLabel)
            composerLabel.autoPinEdgeToSuperviewEdge(.Trailing)
            
            didSetupConstraints = true
        }
        super.updateViewConstraints()
    }
}

总结

如果有一天,你要实现类似的界面,你又刚好想用ScrollView和AutoLayout去实现。
直接上方法:

  • 添加scrollView以及其子视图
    • 父视图.addSubview(scrollView)
    • scrollView.addSubview(container) -- container为一个占位的view
    • container.addSubviews(真·想要展示的views)
  • 拉(或撸)约束
    • scrollView.四边 黏住 父视图.四边
    • container.四边 黏住 scrollView.四边
    • container.width = scrollView.width (如要实现横向滚动,则是container.height = scrollView.height)
    • container.subviews(真·想要展示的views)尽情布局,只需记住一点,拉(或撸)出来的约束要能确定出container的高度(横向滚动则为宽度)
      最直白的布局则像我的Demo中一样:"V:|-[imageView]-[label]-[label]--[contentView]-[label]-|",从上往下一个黏住一个,这样就可以确保高度可以算出来。

补充

对于用代码创建view的朋友,需要记得设置这个东东:

 (scrollView以及其子视图).translatesAutoresizingMaskIntoConstraints = false

再补充

平时本人如果要在ScrollView里使用AutoLayout,都会按照以上方法布局好scrollView与container,如果还有坑,那也基本只是普通的AutoLayout坑了(AutoLayout普通的坑?坑普通的AutoLayout?。。。)

至于这么做的原理是什么,该类文章网上已经有很多,譬如这篇:
这篇
这篇2:
还有我

再推荐一篇文章,里面提到如果scrollView计算出来的contentSize没有超出其本身的size,可在viewDidLayoutSubviews里将控件居中显示的方法:
我是文章

不知道以上内容有没有在你融合AutoLayout和ScrollView的过程中产生一点帮助呢:)有的话麻烦GitHub上star下。

谨以此文致敬尼古拉斯·谢

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,067评论 4 62
  • 我觉得交给,是相互的。 员工的交给是身,心,的交给。 身,以自我健康的体魄为公司做体力上的工作。 心,以自我思想上...
    冰咋吃阅读 214评论 0 3
  • 小裴寄语:你在关系中是习惯了表达吗?你有理有据的诉说自己的种种,却忽视了精妙的语言并不能代替真诚的泪水和美丽的笑...
    潼潼物语阅读 441评论 0 0
  • 五一将近,自驾游的朋友们一定少不了!很多朋友向教授反映:我的车油耗高,每个月的油钱挺多的,这也无形中增加了不少压力...
    小雨茅草屋阅读 151评论 0 1
  • 夜夜夜 北京夜生活分为两种:静吧听听歌喝喝酒或者比较燥的蹦蹦迪。建议你去去静吧感受下就好啊,或者选一个有露台的,看...
    黎芭啦阅读 479评论 0 0