初识iOS9 iPad新特性SlideView和SplitView的适配

摘要:
苹果刚发布了iOS9,在iPad上新增了两个新的特性SlideView和SplitView,前者可以在不关闭当前激活APP的情况下调出来另外个APP以30%比例显示进行操作使用,后者允许同时运行两个APP以50%50%,70%30%比例运行,感觉非常方便。首先代码先在view内增加一个红色的UIView和一个label用于显示当前状态。1程序以SlideView启动。                                2在通过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中对这种情况作了很好的描述,最主要的就是先理解一幅图片。

初识iOS9 iPad新特性SlideView和SplitView的适配第1张

在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个像素。具体的结果如下图:

初识iOS9 iPad新特性SlideView和SplitView的适配第2张

初识iOS9 iPad新特性SlideView和SplitView的适配第3张

上图为正常的全屏,下图为splitView之后的。

首先代码先在view内增加一个红色的UIView和一个label用于显示当前状态。

1      var testingView:UIView!
2      var collectionStateLabel:UILabel!
3 
4         testingView =UIView()
5         testingView.backgroundColor =UIColor.redColor()
6 self.view.addSubview(testingView)
7         
8         collectionStateLabel =UILabel()
9         collectionStateLabel.textAlignment =NSTextAlignment.Center
10         collectionStateLabel.textColor =UIColor.blackColor()
11         self.view.addSubview(collectionStateLabel)   

接着,开始分析实际情况,通过模拟器或者真机使用后就会发现,在应用程序启动的时候就可能出现好几种情况,红色数字代表我的APP显示比例

场景1 如果我正在浏览照片,这时候突然想打开APP查看某样东西的时候那么这时候就会发生几种情况。

1 程序以SlideView启动。                                 (10:3

2 在通过SlideView启动后又展开到了SplitView。                      (5:5

3 在SplitView使用后我觉得不爽,太小了,再想进一步展开又成为全屏。            (0:10

场景2 如果我正在使用APP,这时候我想通过地图查看某幢楼在哪里,这时候又会发生几种情况。

1 程序正在使用时,接受地图程序以slide方式切入,此时地图程序被激活,可以查询地图      (10:3)

2 在查询地图的时候我还要使用回我的APP,这时候我的APP被激活,地图同样被激活        (7:3)

3 我想放大地图程序被地图以SplitView切割成一半显示。                    (5: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 inmake.left.equalTo(self.view.snp_left).offset(100)
                make.right.equalTo(self.view.snp_right).offset(-100)
                make.centerY.equalTo(self.view.snp_centerY)
            }
            return}
        testingView.snp_makeConstraints { (make) -> Void inmake.left.equalTo(self.view.snp_left).offset(100)
            make.right.equalTo(self.view.snp_right).offset(-100)
            make.centerY.equalTo(self.view.snp_centerY)
            make.height.equalTo(60)
        }
    }
    
    func setViewToSlideSplitSize(){
         collectionStateLabel.text = "State:SplitView or SlideView"guard testingView.constraints.isEmpty else{
            testingView.snp_updateConstraints(closure: { (make) -> Void inmake.left.equalTo(self.view.snp_left).offset(10)
                make.right.equalTo(self.view.snp_right).offset(-10)
                make.centerY.equalTo(self.view.snp_centerY)
            })
            return}
        testingView.snp_makeConstraints { (make) -> Void inmake.left.equalTo(self.view.snp_left).offset(10)
            make.right.equalTo(self.view.snp_right).offset(-10)
            make.centerY.equalTo(self.view.snp_centerY)
            make.height.equalTo(60)
        }
    }

我们设置了两个函数第一个函数适配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 inmake.top.equalTo(testingView.snp_bottom).offset(50)
            make.centerX.equalTo(testingView.snp_centerX)
        }

到了这一步已经满足了,APP从slide进来时候的适配。但是,事情还没那么简单,通过场景1,2得出,在不满足当前大小的情况下可以从slide过渡到split,甚至从split过度到regular,那么就牵涉到动态更改布局了,好在Apple的API提供了一个函数来的到当前sizeClass的改变。在viewcontroller中输入以下代码

    overridefunc 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

初识iOS9 iPad新特性SlideView和SplitView的适配第4张

只需要动动鼠标修改下约束也很好的满足实际的情况,只是storyboard的维护性和可读性不是很友好,代码可能会更容易做出修改维护和抽象,实际应用我代码使用的比较多点。

免责声明:文章转载自《初识iOS9 iPad新特性SlideView和SplitView的适配》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇基于React Native的58 APP开发实践CentOS 7 YUM和离线RPM包 升级 Linux 内核下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

linux开机自启动

linux下添加简单的开机自启动脚本 在linux的使用过程中,我们经常会碰到需要将某个自定义的应用程序设置为开机自启动以节省操作时间,这里提供两个设置开机自启动的方法。 注:博主使用的ubuntu-16.04进行实验,其它版本可能有偏差,但实现原理类似。 rc.local 在rc.local脚本中添加开机自启动程序 ubuntu在开机过程之后,会执行/e...

Centos 查看,卸载已安装软件

终于因为工作碰到问题,在网上找了些资料,发现都是比较局限的,我想把它整合在一块,因为公司使用CentOS,所以有这方面的技术需要。 因为我在使用的时候,发现我的软件无法自动更新,所以从网上下了新版本,想说直接右键使用“软件包安装程序”打开安装,结果因为检测到我电脑上有之前版本,所以失败,无法使用这样安装。因此我得先卸载,然后才能安装。 使用RPM: 要知道...

蓝牙BLE控制芯片(6) : 博通BCM20732

北京,2013年6月4日 - 全球有线和无线通信半导体创新解决方案的领导者博通(Broadcom)公司(Nasdaq:BRCM)宣布,推出一款新的蓝牙智能SoC,以推动更广范围的低成本、低功耗外围设备与安卓智能手机和平板电脑配合工作。该公司同时还公布了为安卓开源项目(AOSP)所开发的蓝牙软件栈,其中包括经典蓝牙和蓝牙智能(前身为蓝牙低功耗)技术。博通新推...

Appium(四):真实机第一个appium程序、模拟器第一个appium程序、查看元素

1. 真实机第一个appium程序 学完了前面的知识,也将环境搭建好了,接下来我们就正式开始appium的学习了。 在做app自动化的时候,我们肯定是针对某个产品、某个软件进行测试,那么我们一定是先让模拟器或真机帮我们打开这款软件才可以。所以接下来要学的就是如何打开某个应用程序。 启动步骤: USB连接手机,开启调试模式 打开appium工具 创建pyth...

防止你的iPhone程序遭盗版(入门篇)

转载自:http://www.devdiv.com/%E9%98%B2%E6%AD%A2%E4%BD%A0%E7%9A%84iPhone%E7%A8%8B%E5%BA%8F%E9%81%AD%E7%9B%97%E7%89%88_%E5%85%A5%E9%97%A8%E7%AF%87_-weblog-215400-12864.html 老大让研究app遭盗版...

Django 框架入门篇(安装与创建项目)

什么是Django框架? 官方定义:Django是一个高级Python Web框架,鼓励快速开发和简洁实用的设计。它由经验丰富的开发人员构建,可以解决大部分Web开发的麻烦,因此您可以专注于编写应用程序而无需重复造轮子。 Django is a high-level Python Web framework that encourages rapid de...