浅谈IOS8之size class
以前和安卓的同学聊天的时候,谈到适配一直是一个非常开心的话题,看到他们被各种屏幕适配折磨的欲仙欲死,心里真替他们高兴。不过在做到 iPhone 和 iPad 的适配的时候,一个页面需要配置多个 xib 进行开发还是个很头疼的事情。再加上 iPhone6 和 iPhone6 plus 的发布,适配似乎也变得麻烦起来。今天了解了 iOS8 中的 Size Class 之后,真的笑,笑出声。
简介
先来看一下我们的新伙伴:Size Classes。在 iOS8 中,我们不用再像以前那样,一个页面新建多个 xib 文件来适配不同类型的屏幕,现在我们可以把各种尺寸屏幕的适配工作放在一个文件中完成,然后可以通过不同类别的 Size 来定制各种尺寸的界面。换句话说,你眼前的 Storyboard 不是一个普通的 Storyboard ,而是一个九合一的 Storyboard ,可以管理九种类型的屏幕。
对于宽度和高度而言,都有三种情况:紧凑 (Compact) 、任意 (Any) 、 正常 (Regular) ,所以一共有9个类别,在设置 Size Class 的时候页面会有提示。比如宽为 Compact 高为 Any 的情况,提示为 3.5-inch、4-inch、4.7-inch的横竖状态下的屏幕:

苹果官网文档举了一些例子,比如 iPad :


比如 iPhone :


比如 iPhone6 plus 的横屏状态:

实验
Size Class 的作用是将不同尺寸的屏幕进行分类处理,而最后进行布局管理的还是Autolayout。
下面我们来搞个小项目试验一下。项目源码可以在这里下载。
新建一个项目,进入到 Storyboard ,发现默认的尺寸是宽高均为 Any 的:

我们可以在右侧的视图中选择开启还是关闭 Size Class :

因为 Size Class 是依赖于 Autolayout 的,所以当你尝试关闭 AutoLayout 而打开 Size Class 的时候会有如下的提醒:

接下来我们先搞个 View 看看,测试一下直接扔进去会是什么效果:

看起来好像不错啊,难道不用做适配就可以了?
想太多。
我们把 Size 切换到 Compact 看下:

喔真的好 Compact 啊!
在不手动添加 Constraints 的情况下, Xcode 会自动自动分配一套默认的 Constraints ,以确保你在任何尺寸的屏幕下都看到一样坐标一样大小的页面。这就意味着我们有时可以忽视自动布局,不再需要设置那些自动布局且效果不错的控件,只需要为某些特定的视图创建 Constraints 。
不过现在我们想让这个正方形时刻保持居中,所以分别给它加上了四个 Constraints :

啊哈这样似乎就可以…就可以了…吗?
我们随便换了个 Size 看下效果,突然发现刚刚加的 Constraints 居然无效了,在导航栏里变成了灰色,在 Storyboard 里也看不到 Constraints 的影子:

这是因为刚刚我们的 Constraints 是在宽高均为 Compact 的 Size 中设置的,所以并不适用于其他尺寸的屏幕。这么说难道我们以后都要配置九份 Constraints 吗!这也太苦逼了吧!老板我们要涨工资啊!显然不是,我们只需要把默认的 Constraints 放在宽高均为 Any 的 Size 中即可:

这时再切换到其他尺寸就都没有问题了:

接下来,假设我们想在 iPhone 设备上显示两个 Label ,但是想在 iPad 上显示四个 Label,可以这样搞。
先把 Size 切换到 iPhone 的尺寸,然后添加两个 Label :

再把 Size 切换到 Regular ,添加三个 Label :

这时在 iPhone 中查看一下效果:

再去 iPad 里看下效果:

OK 就是这么简单。
实战
接下来我们来看一看如何利用 Size Class 来做适配。前面有说过, Size Class 不能解决适配问题,它的功能只是将屏幕进行分类,便于管理。真正搞适配的苦力还是 AutoLayout 。苹果的帮助文档给出三种方案解决 View 的适配问题。
我们先把项目改成最原始的版本,只留一个 View 在视图的正中央。原始版本的项目可以在这里下载。运行一下是这样的:

修改 Constraints
适配的第一个方案是针对不同尺寸的屏幕设置不同大小的 Constrain 。
我们选中一个 Constraint ,在右侧面板观察它的属性:

在右侧面板就是 Constraints 的值,第一行是默认值,适用于所有尺寸。如果要添加不同尺寸下的自定义值,可以点击加号:

这样就可以添加自定义的 Constraint 值了。其中, w 和 h 分别指宽 (width) 和 高(height) 。 C是指 Size Class 中的 Compact, R 则对应 Regular , A 对应 Any 。
如果希望这个正方形在 iPad 下可以保持100的边距,在 iPhone 下可以保持0的边距,可以把每个 Constrant 的值都设为100,然后再添加一个 wC hA 的值为0:

运行一下程序看下,首先是 iPad 下:

简直完美,再看下 iPhone4s 下的效果:

哈哈似乎也不错。。。等下,说好的填满呢!怎么左右两边空了这么多空白?
突然想起了前几天在公司用 Xcode6 打开的项目再用 Xcode5 打开之后有些 xib 文件会报错,大意是: Xcode6 加了一些 Margin 我不认识。会不会是这些 Margin 在作怪呢?查了一下官方文档,确实在 iOS8 中多了一个 layoutMargin 的属性。偷偷拿 PS 量了一下,确实默认值是8个 point ,虚惊一场,还以为是 AutoLayout 坏了呢。
不过现在我不是很想要这个 Margin ,怎么把它关了呢?点击下方的 Pin 按钮,把 Margin 的勾选去掉即可:

然后再重新设置一下 Constraint ,OK它终于成功的填满了整个屏幕:

完整的源码可以在这里下载。
安装和卸载 Constraints
有时候我们可能会遇到比较复杂的设计,针对不同的尺寸需要有不同的布局,这和 Web 开发中的响应式设计颇有几分相似。
假设我们需要这样一个 View :在 iPad 下固定宽度,居中对齐,在 iPhone 下,则希望它保持左右边距居中对齐。
我们只需要添加 top 、 bottom 、 center x 、 width ,分分钟就可以搞出这样一个布局:

现在我们完成了第一步:在 iPad 下固定宽度,居中对齐。
接下来我们需要把 width 属性在 iPhone 中删除。选中 width 之后在右侧可以看到这样一个区域:

它表示,当前这个 Constraint 适用宽高均为 Any 的屏幕,和上一步相似,我们可以点击加号添加不同屏幕下的设置:

installed 前面打上勾,表示这个 Constraint 是适用这个尺寸的,如果没有打勾,则表明在那个尺寸下这个 Constraint 是无效的。比如下面的这个例子表示这个 Constraint 仅在宽高均为 Regular 的情况下 ( 也就是 iPad ) 有效:

接下来我们再添加上 leading 和 trailing 为0:

这样就能实现在 iPhone 下保持左右边距居中对齐的效果了:

但是打开 iPad 之后发现本来设置的固定宽度的效果失效了,变成了和 iPhone 一样的左右间距固定的情况。这是因为我们没有在 iPad 的屏幕下“卸载” (uninstall) 掉刚刚设置的 leading 和 trailing 。我们有两种方式解决这个问题。
第一种方案,选中 leading 和 trailing 这两个 Constraint 之后,在右侧添加宽高均为 Regular 的选项并去掉勾选,表明,这个 Constraint 适用于所有情况,就是不要用在宽高均为 Regular 的屏幕上:

第二种方案,切换到 Regular Regular 的尺寸之后,选中那两个 Constraint 然后按下Command+Delete ( 注意要按下 Command 键,要不然就是彻底删除了),就可以把这两个 Constraint 在当前的 Size 中卸载了:

运行一下, iPad 果然也没有问题了:

完整的源码可以在这里下载。
安装和卸载 View
有时候光设置 Constraint 是无法满足比较复杂的需求的,比如大屏下我希望能显示三个按钮,分别对应:吃早饭,吃午饭,吃晚饭。但是在 iPhone 等小屏下可能放不下这么多按钮,只能显示一个按钮:吃饭。遇到这种情况,我们只能对 View 进行安装 (install) 和卸载 (uninstall)。
我们先在 View 里面加上三个按钮:

但是我们并不希望这三个按钮出现在 iPhone 中,所以我们可以在右侧面板添加适用的尺寸,并去掉 Any 的勾选。这一步和上一章中 Constraint 的安装卸载十分类似:

可以看到左侧的 Button 变成了灰色,表示这个按钮在当前 Any 的尺寸下是不会显示的。我们再添加一个吃饭的按钮,添加 Regular 的尺寸并去掉勾选,表明自己不会在 Regular 屏幕中出现:

这样,在 iPhone 中我们可以看到 吃饭 的按钮:

而在 iPad 中可以看到 吃早饭 吃午饭 吃晚饭 的按钮:

完整的源码可以在这里下载。
其他
最后,无意中看到仿佛 Font 的左边多了点什么:

相信大家早已轻车熟路了,不妨动手试试看。可以参考苹果官方的帮助文档学习。
后话
第一次接触 Size Class ,还没有在实际项目中应用过,可能有些理解偏差,如有错误,还望指正,不胜感激。
一路走来,感觉有了 Size Class 之后,iOS 开发的适配工作可能并没有想象中的复杂,哪怕屏幕比更大还大,我们依旧能够真的笑,笑出声。
浅谈IOS8之size class的更多相关文章
- 浅谈IOS8之size class 分类: ios技术 2015-02-05 19:06 62人阅读 评论(0) 收藏
文章目录 1. 简介 2. 实验 3. 实战 3.1. 修改 Constraints 3.2. 安装和卸载 Constraints 3.3. 安装和卸载 View 3.4. 其他 4. 后话 以前和安 ...
- 浅谈RecyclerView(完美替代ListView,GridView)
Android RecyclerView 是Android5.0推出来的,导入support-v7包即可使用. 个人体验来说,RecyclerView绝对是一款功能强大的控件. 首先总结下Recycl ...
- 浅谈php生成静态页面
一.引 言 在速度上,静态页面要比动态页面的比方php快很多,这是毫无疑问的,但是由于静态页面的灵活性较差,如果不借助数据库或其他的设备保存相关信息的话,整体的管理上比较繁琐,比方修改编辑.比方阅读权 ...
- 浅谈JAVA集合框架
浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...
- 浅谈TabLayout(ViewPager+Tab联动)
google发布了的Android Support Design库中提供了TabLayout 通过TabLayout+ViewPager实现导航栏效果,点击Tab ,ViewPager跟随变化,滑动V ...
- 浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的 ...
- 浅谈C中的malloc和free
转自http://bbs.bccn.net/thread-82212-1-1.html非常感谢作者 浅谈C中的malloc和free 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的 ...
- 浅谈开源项目Android-Universal-Image-Loader(Part 3.1)
本文转载于:http://www.cnblogs.com/osmondy/p/3266023.html 浅谈开源项目Android-Universal-Image-Loader(Part 3.1) 最 ...
- C++ STL中的常用容器浅谈
STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用.下面,我们就浅谈某些常用的容器.这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中 ...
随机推荐
- 默认系统为UEFI启动的GPT分区的WIN7(8),如何安装VHD的UEFI WIN8(7)
默认系统为UEFI启动的GPT分区的WIN7(8),如何安装VHD的UEFI WIN8(7) 情况A:如果默认系统为UEFI启动.GPT分区的WIN7,想安装个VHD的UEFI WIN8.1 1:系统 ...
- Struts2龙之总结
一.Struts2执行流程: 1.客户端初始化一个指向servlet容器(tomcat)的请求: 2.这个请求经过一系列过滤器(Filter): 3.接着StrutsPrepareAndExecute ...
- TriggerPrefab 拖拽物体
模拟经营类游戏 有一个特点,就是 拖拽物体.常见的有<帝国><红警><部落战争><凯撒大帝>等等 2d 拖拽 大部分都是 用 OnDrag 方法来 拖动 ...
- Android.mk与jni目录的关系
附1: Android.mk与jni目录的关系: 在某目录下,如/src/modules1/下存放Android.mk和Application.mk,调用ndk-build试图编译时,会遇到如下错误: ...
- HDU 1681 Frobenius(完全背包+标记装满)
一个完全背包,数组两百万,暴力可过 #include<iostream> #include<cstdio> #include<cstring> using name ...
- 如何获取url访问历史记录
在院里的群里,有人问了这么一个问题: A页面提交表单到B页面,然后在B页面点了后退,如果在A页面上判断是直接访问的还是后退进去的呢?我不想改B页面. 于是乎本着热心人的想法,我就帮他搞了搞,首先我想到 ...
- Entity Framework 学习初级篇3-- LINQ TO Entities
LINQ 技术(即 LINQ to Entities)使开发人员能够通过使用 LINQ 表达式和 LINQ 标准查询运算符,直接从开发环境中针对 实体框架对象上下文创建灵活的强类型查询.LINQ to ...
- 理解用requireJs 来实现javascript的模块化加载
这是我看到的一片关于requirejs的初学者的文章,写的不错,下面结合自己的理解记录一下: 原文:http://www.sitepoint.com/understanding-requirejs-f ...
- Naive Bayes在mapreduce上的实现(转)
Naive Bayes在mapreduce上的实现 原文地址 http://www.cnblogs.com/sunrye/p/4553732.html Naive Bayes是比较常用的分类器,因为思 ...
- HDU 2897 邂逅明下(巴什博奕变形)
巴什博奕的变形,与以往巴什博奕不同的是,这里给出了上界和下界,原先是(1,m),现在是(p,q),但是原理还是一样的,解释如下: 假设先取者为A,后取者为B,初始状态下有石子n个,除最后一次外其他每次 ...