初识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的新特性,并整理了一下 ...
随机推荐
- Linux内核--usb子系统的分析
drivers/usb/core/usb.c subsys_init(usb_init); module_exit(usb_exit); 我们 看到一个subsys_initcall,它也是一个宏,我 ...
- Apache的Order Allow Deny心得
Allow和Deny可以用于apache的conf文件或者.htaccess文件中(配合Directory, Location, Files等),用来控制目录和文件的访问授权. 所以,最常用的是: O ...
- [Node.js] npm init && npm install
npm init: For create package.json file which will recode the dependence. npm install: You can also w ...
- 0c-36-自动释放池应用场景
.autorelease的应用场景 经常用来在类方法中快速创建1个对象. // 声明实现一个类方法 + (Student *)student { // 在里面直接进行autorelease retur ...
- IT思想类智力题
1. 台阶问题 题目:一个人上台阶可以一次上一个或两个,问这个人上n层的台阶,一共有多少种走法. 本题可以采用递归的方法来设计模型,先从数字的规律入手:假设共有i阶台阶,走完所有的台阶有n种走法,则存 ...
- RSA非对称算法(转)
RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它.但是有不少新来的同事对它不太了解,恰好看到一本书中作者用实例对它进行了简化而生动的描述,使得高深的数学理论能够被容易地理解.我们经 ...
- 史上最详细版!java文件打包成exe,在未配置安装JDK和未配置的电脑上运行--转载
原文地址:http://funine.iteye.com/blog/2220359 (本文所有素材将在文章最后附上) 准备工具exe4j, converticon.com(用于制做.ico格式的图片) ...
- 如何通过apt-get获得安装包的源码
有时候我们需要获得某个可执行程序的源码,而不仅仅是一个可执行程序,比如我们想获取tree这个工具的源码,这时候就可以采用下面的命令: sudo apt-get source tree pengdl@d ...
- 汇编中 .fill 的作用
.fill 语法:.fill repeat, size, value 含义是反复拷贝 size个字节,重复 repeat 次, 其中 size 和 value 是可选的,默 ...
- 请谨慎使用 @weakify 和 @strongify
来源:酷酷的哀殿 链接:http://www.jianshu.com/p/d8035216b257 前言 相信大部分见过 @weakify 和 @strongify 的开发者都会喜欢上这两个宏.但是很 ...