-

一、和横屏相关的系统api

(一)绝对参数

UIDeviceOrientation : 表示设备物理方向的枚举。
UIInterfaceOrientation : 应用程序界面方向的枚举,它基于应用程序的界面布局。

那通过 UIScreen.mainScreen 获取的高度,和 UIDeviceOrientation 还是 UIInterfaceOrientation 更匹配? 
UIScreen.mainScreen 获取的高度与 UIInterfaceOrientation更匹配 ,即使手机横屏了,只要应用还是竖屏,那么通过 mainScreen 获取到的高度就是竖屏。

(二)变更时机

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

二、横屏方案

因为iPad天然就支持横竖屏,但iPhone在主流的场景中只有针对横屏的视频才会进行横屏,所以我们将iPhone和iPad分开进行讨论。

横屏从主流的场景上有两种方案,第一种是修改tableView的frame,第二种是只调节UITableViewCell的frame,tableView的frame并不改变。

第一种方案的好处是实现demo比较简单,但这套方案在iPhone上容易遇到各种非常难查的问题。

第二种方案的好处是实现demo比较麻烦,但这套方案的好处是后续状态管理更加简单。

(一)iPad适配

在iPad上的横竖屏,本质上对应的tableView的旋转,所以在iPad上我们可以直接使用修改tableView.frame的方式即可。

(二)iPhone适配

iPhone上的横屏方案很值得讨论,如果诉求是老板让你快速出一个demo,那么在横屏的时候修改tableView的frame是最简单的(也就是第一种方案),但是!

这种方案最大的问题就是状态管理问题。

方案1. 修改tableView的frame方案

我举例说明:因为你在横屏时把整个tableView的frame都进行修改了,再加上因为tableView有提前创建和复用的技术,

当你切成竖屏时,你不能只刷新当前cell,你需要保证所有cell的状态都恢复成竖屏。

我们就遇到过一类非常恶心的系统bug,在横屏切换到竖屏时,[UiUtil currentInterfaceOrientation] 获取到的方向是 竖屏,但通过 [[UIScreen currentScreen] bounds].size.height 获取到的高度是 横屏 的。

可以发现,如果采用这种方案,你会有非常多的状态是依赖系统接口的,但系统接口的变更没有保证原子性(比如上面获取的是竖屏,但获取的高度实际是横屏的),所以你会遇到很多棘手头疼的bug。

为了规避因为过度依赖系统接口导致的千奇百怪的bug,我们看看方案2

方案2. 调整cell的layout

这种方案,不需要修改tableView的frame,我们只需要根据一个状态标志位,来对应调整cell的layout就可以,这种方案的好处很明显,

首先是可以规避方案1中因为修改了全局tableView的frame,导致非横屏的cell的frame也错位的情况。

其次是我们不再强依赖系统接口,而是依靠本地维护的一个标志位即可。

但这个方案的最大问题,就是前期搭建不如直接收到系统回调那么舒服,需要自己适配layout。

三、横屏优化

好了,讨论完方案1和方案2,我们聊一下体验的优化。

可以看到无论是方案1还是方案2,都对view的frame进行了调整,为了避免隐式动画可能造成的view元素漂移的问题。

我们可以在 横屏开始前->横屏完成后 ,这个过程中加个动画,在页面上贴一个假的截图View,这样会让体验更加丝滑。