初识iOS9 iPad新特性SlideView和SplitView的适配
苹果刚发布了iOS9,在iPad上新增了两个新的特性SlideView和SplitView,前者可以在不关闭当前激活APP的情况下调出来另外个APP以30%比例显示进行操作使用,后者允许同时运行两个APP以50%50%,70%30%比例运行,感觉非常方便。
然而,方便了用户的同时却恶心了开发者,在同一屏幕运行两种APP的时候势必APP显示比例发生改变,那么就需要对几种不同的大小进行处理,好在苹果有Autolayout,并且在iOS8中新增了SizeClass特性,两者结合,可以很好的应付以上各种情况。
好了,为了适配iOS9上述的特性,先来看下苹果的文档说明来如何处理多种显示比例的问题。Adopting Multitasking Enhancements on iPad中对这种情况作了很好的描述,最主要的就是先理解一幅图片。

在iOS8中新增的SizeClass能很好理解图片的内容,C(Compact)紧凑,R(Regular)常规,通过C和R的组合可以匹配出各种屏幕,如果不理解最直观的可以查看StoryBoard中设置Autolayout时候在底部出现的w Any h Any通过鼠标移动可以得出各种组合后能适配哪一种屏幕,这里就不再阐述。
此图可见,在iPad标准的屏幕比例种,width和height都是R,也就是说无论横屏还是竖屏都是常规的组合即wR hR,然而在出现split和slide后状态即发生的改变,在竖屏状态下APP被分割后出现了wC hR,在横屏状态下,又出现了两种组合分别是主APP70%从APP30%和主APP50%从APP50%,通过图片得出在横屏7:3中,主APP比例是wRhR,从APP比例是wChR,在5:5情况下主从APP都是wChR,那么就此知道了APP在slideView和splitView状态下的各种高宽组合。
总结一下APP在Slide和Split后的各种需要适配的尺寸是,100%常规状态,70%作为主APP的状态,50%作为split等分的状态,30%作为从APP出现时候的状态。由于100%和70%都属于wRhR,那么我们主要适配就分成三中情况 100%,50%,30%,如果APP界面主要以list为主或者比较简单的布局,其实只要适当调整Autolayout的offset值即可适配所有的情况,那么如果是比较复杂的界面或者需要满足各种状态下的显示怎么办呢,当然是有解决的方案,以下主要以简单代码的例子进行适配工作,主要理解原理和知道什么时候触发显示比例改变,还有种方法是通过Storyboard的SizeClass匹配上述所有状况并且逐一调整差值,这种方式比较简单用惯XIB的应该很容易解决,缺点就是维护起来稍微不方便。
首先,有个需求,在屏幕当中放置一个红色的UIView,在正常状态下,左右两边距边框100个像素,并且有个label显示当前的比例,当出发split或者slide的时候,UIView的左右边框调整为10个像素。具体的结果如下图:


上图为正常的全屏,下图为splitView之后的。
首先代码先在view内增加一个红色的UIView和一个label用于显示当前状态。
var testingView:UIView!
var collectionStateLabel:UILabel! testingView = UIView()
testingView.backgroundColor = UIColor.redColor()
self.view.addSubview(testingView) collectionStateLabel = UILabel()
collectionStateLabel.textAlignment = NSTextAlignment.Center
collectionStateLabel.textColor = UIColor.blackColor()
self.view.addSubview(collectionStateLabel)
接着,开始分析实际情况,通过模拟器或者真机使用后就会发现,在应用程序启动的时候就可能出现好几种情况,红色数字代表我的APP显示比例
场景1 如果我正在浏览照片,这时候突然想打开APP查看某样东西的时候那么这时候就会发生几种情况。
1 程序以SlideView启动。 (10:)
2 在通过SlideView启动后又展开到了SplitView。 (5:)
3 在SplitView使用后我觉得不爽,太小了,再想进一步展开又成为全屏。 (0:)
场景2 如果我正在使用APP,这时候我想通过地图查看某幢楼在哪里,这时候又会发生几种情况。
1 程序正在使用时,接受地图程序以slide方式切入,此时地图程序被激活,可以查询地图 (:3)
2 在查询地图的时候我还要使用回我的APP,这时候我的APP被激活,地图同样被激活 (:3)
3 我想放大地图程序被地图以SplitView切割成一半显示。 (:5)
从上总结出来,场景1我的APP是作为从APP存在,照片是主APP,场景2我的APP是作为主APP存在,地图程序是从APP,其实这都不重要,最主要的得出结论就是在布局的时候一开始就必须考虑到针对不同的场景以适应不同的布局需求。
现在开始代码布局,代码布局使用了一个第三方的类库以节省代码量,Apple的API实在非常的繁琐,在此使用SnapKit作为布局类库 (https://github.com/SnapKit/SnapKit),OC版本(https://github.com/SnapKit/Masonry)
从场景1,2分析出在一开始就需要知道当前的屏幕处在什么样的比例之中,那么通过文章一开始分析的Apple文档得出在slide和split下的比例都是wC hR也就是说宽是紧凑竖是标准。那么通过SizeClass的API就可以判断出来。
if self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.Regular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact{
//slide or split size slide和split状态
}else{
//regular size 标准状态
}
通过 UITraitCollection 类可以获取当前屏幕处在什么样子的比例当中 ,这个类封装了各种水平竖直方向等SizeClass的信息,通过实现了UITraitEnvironment接口的对象都可以拿到这个属性,(UIViewController,UIView,UIWindow,UIScreen都实现了这个接口)。通过判断属性verticalSizeClass和horizontalSizeClass的各种组合即可很容易获取到当前屏幕水平垂直配比。
至此,屏幕显示比例判断出来了,那么就根据需求和实际情况分别编写不同比例下的适配代码即可,这里根据需求在regular下按钮左右边距100像素,在split下按钮左右10个像素。
func setViewToRegularSize(){
collectionStateLabel.text = "State:Regular View"
guard testingView.constraints.isEmpty else{
testingView.snp_updateConstraints { (make) -> Void in
make.left.equalTo(self.view.snp_left).offset()
make.right.equalTo(self.view.snp_right).offset(-)
make.centerY.equalTo(self.view.snp_centerY)
}
return
}
testingView.snp_makeConstraints { (make) -> Void in
make.left.equalTo(self.view.snp_left).offset()
make.right.equalTo(self.view.snp_right).offset(-)
make.centerY.equalTo(self.view.snp_centerY)
make.height.equalTo()
}
}
func setViewToSlideSplitSize(){
collectionStateLabel.text = "State:SplitView or SlideView"
guard testingView.constraints.isEmpty else{
testingView.snp_updateConstraints(closure: { (make) -> Void in
make.left.equalTo(self.view.snp_left).offset()
make.right.equalTo(self.view.snp_right).offset(-)
make.centerY.equalTo(self.view.snp_centerY)
})
return
}
testingView.snp_makeConstraints { (make) -> Void in
make.left.equalTo(self.view.snp_left).offset()
make.right.equalTo(self.view.snp_right).offset(-)
make.centerY.equalTo(self.view.snp_centerY)
make.height.equalTo()
}
}
我们设置了两个函数第一个函数适配regular的情况,第二个函数适配Split或Slide的情况,并且分别在label上标注,这里使用了swift guard ... else {}来判断如果约束不为空则更新约束,否则新增约束,关于snapkit用法具体请看GIT上说明,这里仅仅举例。现在分别在初始化时候调用相应的函数即可完成APP启动时候的显示适配。并且给label上好约束。
if traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.Regular && self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact{
//slide or split size
self.setViewToSlideSplitSize()
}else{
//regular size
self.setViewToRegularSize()
}
collectionStateLabel.snp_makeConstraints { (make) -> Void in
make.top.equalTo(testingView.snp_bottom).offset()
make.centerX.equalTo(testingView.snp_centerX)
}
到了这一步已经满足了,APP从slide进来时候的适配。但是,事情还没那么简单,通过场景1,2得出,在不满足当前大小的情况下可以从slide过渡到split,甚至从split过度到regular,那么就牵涉到动态更改布局了,好在Apple的API提供了一个函数来的到当前sizeClass的改变。在viewcontroller中输入以下代码
override func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.willTransitionToTraitCollection(newCollection, withTransitionCoordinator: coordinator)
if newCollection.verticalSizeClass == UIUserInterfaceSizeClass.Regular && newCollection.horizontalSizeClass == UIUserInterfaceSizeClass.Compact{
self.setViewToSlideSplitSize()
}else{
self.setViewToRegularSize()
}
}
这个函数类似于以前willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval)处理旋转屏幕的逻辑一样,当sizeClass发生改变后立即会得到调用,那么在这个函数内根据Apple文档提供的slide和split的比例规则也非常容易对当前布局进行更新。
至此,我们已经完全满足了需求和场景1和2的各种情况,综上所述,只要知道sizeClass的各种比例组合就可以轻松应付各种屏幕显示发生改变的情况,再通过与Autolayout的配合,达到满足各种尺寸及动态改变尺寸需求。最后,虽然苹果引入的新的特性,看似复杂,其实还是使用老的技术来解决各种情况,sizeClass和autolayout配合犹如双剑合壁,无惧任何尺寸大小的变更。
题外话,如果习惯使用XIB的话用法还是和之前的一样,只需要匹配各种Compact和Regular的组合并且设置好相应的约束并且Install对应的View也非常容易对付Slide和Split

只需要动动鼠标修改下约束也很好的满足实际的情况,只是storyboard的维护性和可读性不是很友好,代码可能会更容易做出修改维护和抽象,实际应用我代码使用的比较多点。
初识iOS9 iPad新特性SlideView和SplitView的适配的更多相关文章
- iOS开发——新特性OC篇&IOS9 系统新特性
IOS9 系统新特性 2015年6月89号凌晨召开的WWDC 2015苹果开发者大会发布了全新的iOS 9系统,PC6小编今天给大家整理了这次iOS9的系统更新带来了哪些新的功能与升级,本次新功能一览 ...
- iOS开发——新特性OC篇&IOS9 SDK新特性
iOS9 SDK新特性 WWDC 2015苹果开发者大会是移动开发者一年一度的盛会,InfoQ中文站除了第一时间整理Keynote内容分享给大家之外,还邀请了资深的一线开发者分享他们的收获.本文为王巍 ...
- 转:iOS9的新特性以及适配方案
2015年9月8日,苹果宣布iOS 9操作系统的正式版在太平洋时间9月16日正式推出,北京时间9月17日凌晨1点推送. 新的iOS 9系统比iOS8更稳定,功能更全面,而且还更加开放.iOS 9加入了 ...
- iOS9的新特性以及适配方案-----转载
2015年9月8日,苹果宣布iOS 9操作系统的正式版在太平洋时间9月16日正式推出,北京时间9月17日凌晨1点推送. 新的iOS 9系统比iOS8更稳定,功能更全面,而且还更加开放.iOS 9加入了 ...
- iOS9 collectionView新特性
近日因为系统升级导致xcode6.系列版本出现bug,于是开始使用xcode7.在使用之余突然想到collectionView在iOS9中发布了一个可以移动cell的新特性,就尝试着将其实现,无奈ap ...
- Android7.0新特性,及Android N适配
新特性部分 Android 7.0 Nougat 提供新功能以提升性能.生产效率和安全性,主要新增了下面的新特性和优化: 一.新的Notification Android N 添加了很多新的notif ...
- iOS9的新特性以及适配方案
新的iOS 9系统比iOS8更稳定,功能更全面,而且还更加开放.iOS 9加入了更多的新功能,包括更加智能的Siri,新加入的省电模式.iOS 9为开发者提供5000个全新的API. 1. 限制HTT ...
- iOS9 开发新特性 Spotlight使用
1.Spotloight是什么? Spotlight在iOS9上做了一些新的改进, 也就是开放了一些新的API, 通过Core Spotlight Framework你可以在你的app中集成Spotl ...
- ios9和ios10的新特性
昨天面试了一个做ios开发的公司,其中面试官问我最新的ios系统版本是多少,以及它的特性是什么?由于自己是初学者,所以对这些没有关注过.今天特地搜索了一下关于ios9和ios10的新特性,并整理了一下 ...
随机推荐
- .net+mssql制作抽奖程序思路及源码
近期一直在研究数据库,刚好有个项目要做抽奖程序,恩,拿来练练手吧. 抽奖程序: 思路整理,无非就是点一个按钮,然后一个图片旋转一会就出来个结果就行了,可这个程序的要求不是这样的,是需要从数据库中随机抽 ...
- Fox Roddick interviw Federer before 2013 US Open
talk about Mike Jordan , talk about Tiger Woods, their competitor when people discuss you I love wi ...
- 离线安装Android开发环境的方法
对于大家从官网上下载下来的SDK其实是一个安装工具,里面啥都没有,如果在线安装的话会需要很长时间.我们同样可以从网络上用下载工具将所需要安装的东西下载下来,(同样有劳大家自己动手找找了)然后直接放入相 ...
- 【JavsScript】JavaScript MVC 框架技术选型
你很喜欢Gmail和Trello之类的单页面应用,但是不太确定该从何开始.也许你的JavaScript代码是如此的杂乱无章,以致于你很想在下一个项目上尝试下JavaScript MVC库和框架,却苦于 ...
- docker(4):coreos+docker+rancher真厉害
http://blog.csdn.net/freewebsys/article/category/3103827
- 实现一个不停发包的Android应用(类似于电脑上的Ping命令)
代码如下: package com.example.ping; import java.io.BufferedReader; import java.io.IOException; import ja ...
- Selenium1(RC)与Selenium2(WebDriver)的概念介绍
最近网上学习了Selenium1和selenium2,自己做一些总结,方便以后查阅. 部分内容引用: http://www.cnblogs.com/hyddd/archive/2009/05/30/1 ...
- Linux Shell远程执行命令(命令行与脚本方式)
需求:经常需要在一台服务器远程到其他节点的服务器上执行一些shell命令,如果分别ssh到每台主机上再去执行很麻烦,因此能有个集中管理的方式就好了.介绍两种shell命令远程执行的方法. 方式一: s ...
- 修改FFMpeg源码—捕获丢包
概述 最近我们项目有一个需求就是解决客户端播放RTSP视频流花屏的问题,一般来说丢包就会引起花屏,导致客户端花屏的因素又有很多,比如说: 相机到服务器丢包 服务器到客户端丢包 等等... 其中服务器到 ...
- entity framework 连接 oracle 发布后出现的问题(Unable to find the requested .Net Framework Data Provider)
用entity framework 搭建的一个windows 程序,在vs中用oracle 的ODT 工具连接oracle数据库,昨天发布后出现下面一个错误, System.ArgumentExcep ...