iOS: How To Make AutoLayout Work On A ScrollView

Posted on June 11th, 2014

Ok, I’ll admit. I’ve been seriously struggling with AutoLayout ever since it’s been introduced. I understand the concept, and I LOVE the idea of it, but when I actually do it, it almost never behaves as it does in my head.

So when I had a chance to go talk to an actual Apple Engineer about AutoLayout last week at WWDC, I made sure to go. I thought of my most painful experience using AutoLayout recently – when I was making a login screen with username and password fields on a ScrollView (so it scrolls up when the keyboard comes up) – and had the Apple engineer walk me through the example.

Here is what we made:

 

This is just two input fields centered on a ScrollView. You can see the AutoLayout at work here – the two input fields are centered correctly both on a 4s and a 5s device.

This “simple” solution took the Apple Engineer 40 minutes to solve! However, several senior engineers I know said that they’ve never been able to get AutoLayout working quite right on a ScrollView, so 40 minutes is actually not bad!

Here are the key tricks to getting AutoLayout to work on a ScrollView:

One View

The ScrollView should have only ONE child view. This is forced in Android, so I should have made the connection, but I just didn’t think of it – it’s too easy to put the two input text fields right onto the ScrollView, especially in Interface Builder.

Here is what the View Hierarchy should actually look like:

Again, make sure to put all your fields and custom views inside the one child view of the ScrollView!

Equal Widths

I’m going to start with the constraints from the outside (on the main view) in (to the stuff inside the ContentView).

The obvious starting point is to bind the ScrollView to the View – just select the ScrollView from the view hierarchy, and add the following constraints:

The key to getting the constraints to work properly however, is adding anEqual Width constraint between the main View and the ContentView. The ScrollView adjusts to the size of the content inside of it, so setting the ContentView to the Width of the ScrollView leaves the width of the ContentView ambiguous.

To create the Equal Width Constraint between the ContentView and the View, select the ContentView on the view hierarchy and Control + Drag to the View – you should get a pop-up that gives you the “Equal Widths” option:

Your constraints between the main View, ScrollView, and ContentView should look like this:

Content Insets

The constraints between the ScrollView and the ContentView are surprisingly straight forward – just bind the ContentView to the ScrollView (make sure the constant to the bottom layout guide is 0):

The constraints between the ContentView and ScrollView are now as follows with all constants set at 0:

If your storyboard is like mine, you might notice that the actual ContentView is not the full height of the main view or the ScrollView:

However, we do want to make sure the ContentView is centered when it’s rendered on a device. To do that we need to write some code to property set the Content Insets in the ViewController:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// ViewController.swift
 
import UIKit
 
class ViewController: UIViewController {
                             
    @IBOutlet var scrollView : UIScrollView
    @IBOutlet var contentView : UIView
     
     
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
 
    override func viewDidLayoutSubviews()
    {
        let scrollViewBounds = scrollView.bounds
        let containerViewBounds = contentView.bounds
         
        var scrollViewInsets = UIEdgeInsetsZero
        scrollViewInsets.top = scrollViewBounds.size.height/2.0;
        scrollViewInsets.top -= contentView.bounds.size.height/2.0;
         
        scrollViewInsets.bottom = scrollViewBounds.size.height/2.0
        scrollViewInsets.bottom -= contentView.bounds.size.height/2.0;
        scrollViewInsets.bottom += 1
         
        scrollView.contentInset = scrollViewInsets
    }
 
 
}

Once you add the proper constraints into the ContentView (see next step), your final result will look like this:

The ugly colors are meant to differentiate the ScrollView (green) from the ContentView (red). Again, in the storyboard, the ContentView is at the top of the ScrollView, but with our content insets set in code, it now becomes centered.

Centering Multiple Views

The final step is to add AutoLayout to the ContentView. This is the same as adding layout normally to any view, so I won’t go into much detail here.

The one thing I did learn that I’d like to share (although now it seems obvious) is how to center the two text fields in the view. Previously, I put the two text fields into a container view, and centered the container view in the parent view. However, that is not necessary.

Instead, you can center each text field horizontally in container (so they’re now centered and on top of each other), and then add a constant of 25 to one (so it’s moved up 25 pixels from the center), and add a constant of -25 to the other (so it’s moved down 25 pixels from the center).

 

This will leave you with a space of 50 pixels between the two text fields, but the space exactly in between them will be the center of the view.

Do you have any other AutoLayout tips? I’m always looking to learn more and improve, so please let me know in the comments!

You can view the source code on Github here.

Enjoy the article? Join over 8,500+ Swift developers and enthusiasts who get my weekly updates.

Subscribe

iOS: How To Make AutoLayout Work On A ScrollView的更多相关文章

  1. iOS开发——使用基于Autolayout的ScrollView

    问题描述: 在使用Autolayout布局方式对ScrollView进行布局时,如果你想做一个可以垂直方向滚动的九宫格类似这样:   拿一行来说,一定不要想当然的尝试去给一行图标进行均匀排列的操作(指 ...

  2. iOS 屏幕适配:autoResizing autoLayout和sizeClass

    1. autoResizing autoresizing是苹果早期的ui布局适配的解决办法,iOS6之前完全可以胜任了,因为苹果手机只有3.5寸的屏幕,在加上手机app很少支持横屏,所以iOS开发者基 ...

  3. 一篇文章详解iOS之AutoResizing、AutoLayout、sizeClass来龙去脉

    前言 iPhone自诞生以来,随着其屏幕尺寸不断的多样化,屏幕适配的技术一直在发展更新.目前,iOS系统版本已经更新到9.3,XCode的最新版本已经是7.3,仅iPhone历史产品的尺寸就已经有4种 ...

  4. iOS开发——modifying the autolayout engine from a background thread

    很多时候,我们需要用到多线程的东西,比如红外线检测是否有人经过.这种情况需要搞个子线程在后台不断的检测,这个线程可能是第三方提供的,你调用它给的方法,然后显示提示框的时候,问题就来了. 提示信息:Th ...

  5. iOS 8 UI布局 AutoLayout及SizeClass(二)

    一.新特性Size Class介绍 随着iOS8系统的公布,一个全新的页面UI布局概念出现,这个新特性将颠覆包含iOS7及之前版本号的UI布局方式,这个新特性就是Size Class. Size Cl ...

  6. iOS 小 Tip:优化侧滑返回与 ScrollView 的兼容性

    http://www.cocoachina.com/ios/20150909/13369.html 作者:@周楷雯Kevin 授权本站转载. 倘若在 ViewController 中添加了一个 Tab ...

  7. iOS学习笔记——AutoLayout的约束

    iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...

  8. iOS屏幕适配

    ## iOS屏幕适配 ### iOS屏幕适配发展史 1> iPhone4以前(没有iPad) * 不需要屏幕适配 2> iPad.iPhone5等设备出现 * 需要做横竖屏适配 * aut ...

  9. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

随机推荐

  1. Calculator(补)

    MyGitHub 刚刚开始时确实是连题目都看不懂= =,从第二行的新建类开始,就不知题目所云.所以我的困难比很多同学都要 开始得早一些--从题目第二行开始. 准确的说,当我按照题目要求新建了一个sca ...

  2. .NET的面向对象

    一.继承 1.C#中的继承规则 继承是可传递的 派生类是对基类的扩展 构造函数和析构函数不能被继承 派生类可以覆盖已继承的成员 派生类只能从一个类中继承,可以通过接口来实现多重继承 类可以定义虚属性. ...

  3. 代码成长记录之jquery this使用

    后台管理的一个项目,第一次主动尝试自己动手写交互,果然问题来了,之前想当然觉得自己能写,不动笔,真的是对自己不负责任啊! 效果图是这样的,按我的思维写下来是点击一个‘更改’  多个地方会同时触发下拉 ...

  4. 10.6 CCPC northeast

    1001 Minimum's Revenge 点的编号从 1 到 n ,u  v 的边权是 LCM(u,v) ,求这个图的最下生成树 搞成一颗以 1 为 根 的菊花树 ---------------- ...

  5. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(完)

    前言 这一篇是本系列的最后一篇,虽然示例讲到这里就停止呢,但对于这些技术的学习远不能停止.虽然本示例讲的比较基础,但是正如我第一篇说到的,这个系列的目的不是说一些高端的架构设计,而是作为一个入门级,对 ...

  6. qml中打开本地html

    main.cpp QString tmploc = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); QDi ...

  7. 列王的纷争,COK,675区,有去的没有?加群:159108918,盟的名字准备叫:大话西游

    首先我承认我玩物丧志了 679区,有去的没有?加群: 474574809,盟的名字叫:Moon Box 如何练最强5级号,为新区做准备?! 粮食是可以为0的,士兵不会死,这是关键之一. 关键之二是新手 ...

  8. Ajax实现原理

    Ajax的工作 Ajax直觉认识:我们发送一个请求,但是这个请求比较特殊它是异步的,也就是说客户端是不会感觉到的.在发送这个请求的时候我们绑定了一个事件,这个事件会监控我们发送请求的状态,并且每次状态 ...

  9. 转载:CDH5.X完全卸载步骤

    http://blog.csdn.net/wulantian/article/details/42706777 //CDH5.X完全卸载步骤 # by coco # 2015-01-14   1. 关 ...

  10. Scala编程--函数式对象

    本章的重点在于定义函数式对象,也就是说,没有任何可变状态的对象的类.作为运行的例子,我们将创造若干把分数作为不可变对象建模的类的变体.在这过程中,我们会展示给你Scala面向对象编程的更多方面:类参数 ...