iOS: How To Make AutoLayout Work On A ScrollView

转载自: http://natashatherobot.com/ios-autolayout-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:

ScrollView TextFields Autolayout ScrollView AutoLayout 5

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:

scrollview hierarchy

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:

constraints

The key to getting the constraints to work properly however, is adding an Equal 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:

equal width option

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

Equal Widths

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):

constraints

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

scrollview to contentview

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:

storyboard views

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:

centered container view

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).

top 25 bottom -25

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.

转载于:https://www.cnblogs.com/zsw-1993/p/4879192.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/273574.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows 中搭建Zookeeper的搭建

个人博客 :https://www.siyuan.run CSDN:https://blog.csdn.net/siyuan 微信小程序:思远Y 下载 下载地址: https://mirrors.cnnic.cn/apache/zookeeper/ PS:zookeeper 从3.5.5以后的版本带有bin标识的包,否…

Vs Code:Remote SSH

Remote SSH 简介 Remote - SSH 扩展允许您使用任何带有 SSH 服务器的远程计算机作为开发环境。由于几乎每个桌面和服务器操作系统都有可配置的 SSH 服务器,因此该扩展可以在各种情况下大大简化开发。 您可以: 在部署的同一操作系统上进行开发&#xff…

样条之贝塞尔(Bezier)

我曾经发过两篇关于贝塞尔的文章:数学图形(1.47)贝塞尔(Bzier)曲线,数学图形之贝塞尔(Bzier)曲面。那是使用我自己定义的脚本语言生成贝塞尔图形。由于我自己定义的脚本语法功能有限,所以最多只能支持5次贝塞尔函数,而这里将实现N…

设计模式 之 工厂模式

项目源码:https://gitee.com/Jacob-gitee/DesignMode 个人博客:https://jacob.org.cn 女娲造人的故事 东汉《风俗通》记录了一则神话故事:“开天辟地,未有人民,女娲搏黄土做人”,讲述的内容就是大家非常熟…

设计模式 之 单例模式

项目源码:https://gitee.com/Jacob-gitee/DesignMode 个人博客:https://jacob.org.cn 宗旨 Ensure a class has only one instance,and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个…

设计模式 之 抽象工厂模式

项目源码:https://gitee.com/Jacob-gitee/DesignMode 个人博客 :https://jacob.org.cn 女娲的失误 工厂模式中讲了女娲造人的故事。人是造出来了,世界也热闹了,可是低头一看,都是清一色的类型,缺少关爱、仇…

设计模式 之 模板模式

项目源码:https://gitee.com/Jacob-gitee/DesignMode 个人博客 :http://jacob.org.cn 女娲的失误 工厂模式中讲了女娲造人的故事。人是造出来了,世界也热闹了,可是低头一看,都是清一色的类型,缺少关爱、仇…

使用Java高速实现进度条

基于有人问到如何做进度条,以下给个简单的做法: 主要是使用JProgressBar(Swing内置javax.swing.JProgressBar)和SwingWorker(Swing内置javax.swing.SwingWorker) 有人肯定会说,不是用线程做的吗…

关于js的function.来自百度知道的回答,学习了.

在js中,创建一个函数对象的语法是var myFunction new Function(arg1,…,agrN, body);其中,该函数对象的N个参数放在 函数主体参数body的前面,即函数主体参数必须放在参数列表的最后,也可以无参数new Function(body)。你添加第三个…

fedora20开机启动配置:systemctl

老版fedora中使用chkconfig配置开机启动,fedora20中,使用chkconfig会出现各种问题。使用systemctl配置。 具体表格如下 转载于:https://www.cnblogs.com/hh6plus/p/5548083.html

《Java 高并发》01 高并发基本概念

基本概念 同步和异步 同步和异步通常是用来形容一次方法调用。 同步方法调用一旦开始,调用者必须等到方法返回才能继续执行后续操作。 异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操…

Android之Http网络编程(四)

前面几篇博文简单的介绍了一些常见的Http的操作,这些操作几乎都是在新开的线程中进行的网络请求,并在日志中打印出获取到的网络数据。那么,问题来了!(呃~感觉下一句是蓝翔有木有?)如何在把获取到…

mybatis 2 -常用数据操作

1、写入数据并获取自增ID XML配置&#xff1a; <!-- 写入数据获取自增ID --><insert id"insertLog" parameterType"com.mamaguwen.entity.sys_loginlog" useGeneratedKeys"true" keyProperty"logid">insert into sys_…

Docker 搭建 ELK 日志系统,并通过 Kibana 查看日志

Docker 搭建 ELK 日志系统,并通过 Kibana 查看日志 docker-compose.yml version: 3 services:elasticsearch:image: elasticsearch:7.7.0 #镜像container_name: elasticsearch #定义容器名称restart: always #开机启动&#xff0c;失败也会一直重启environment:- "cl…

RabbitMQ Management:Management API returned status code 500

错误显示&#xff1a; 解决方案&#xff1a; 因为是使用docker 容器安装的&#xff0c;所有需要进入容器 docker exec -it rabbitmq /bin/bash进入目录 cd /etc/rabbitmq/conf.d/执行命令 echo management_agent.disable_metrics_collector false > management_agent.dis…

c++ 读取文件 最后一行读取了两次

用ifstream的eof()&#xff0c;竟然读到文件最后了&#xff0c;判断eof还为false。网上查找资料后&#xff0c;终于解决这个问题。 参照文件&#xff1a;http://tuhao.blogbus.com/logs/21306687.html 在使用C/C读文件的时候&#xff0c;一定都使用过eof&#xff08;&#xff0…

java中的io系统详解(转)

Java 流在处理上分为字符流和字节流。字符流处理的单元为 2 个字节的 Unicode 字符&#xff0c;分别操作字符、字符数组或字符串&#xff0c;而字节流处理单元为 1 个字节&#xff0c;操作字节和字节数组。 Java 内用 Unicode 编码存储字符&#xff0c;字符流处理类负责将外部的…

Unity3D Shader入门指南(二)

关于本系列 这是Unity3D Shader入门指南系列的第二篇&#xff0c;本系列面向的对象是新接触Shader开发的Unity3D使用者&#xff0c;因为我本身自己也是Shader初学者&#xff0c;因此可能会存在错误或者疏漏&#xff0c;如果您在Shader开发上有所心得&#xff0c;很欢迎并恳请您…

JVM:如何分析线程堆栈

英文原文&#xff1a;JVM: How to analyze Thread Dump 在这篇文章里我将教会你如何分析JVM的线程堆栈以及如何从堆栈信息中找出问题的根因。在我看来线程堆栈分析技术是Java EE产品支持工程师所必须掌握的一门技术。在线程堆栈中存储的信息&#xff0c;通常远超出你的想象&…

SQLSERVER中如何忽略索引提示

SQLSERVER中如何忽略索引提示 原文:SQLSERVER中如何忽略索引提示SQLSERVER中如何忽略索引提示 当我们想让某条查询语句利用某个索引的时候&#xff0c;我们一般会在查询语句里加索引提示&#xff0c;就像这样 SELECT id,name from TB with (index(IX_xttrace_bal)) where bal…