通话状态下的UI优化

最近在开发过程中遇到一个比较特殊的优化点,在通话过程中APP UI会有下压被部分遮盖的问题。

以前偶尔在使用别的APP的时候也会遇到这个问题,但是当时并没有太在意,因为UI下移了一小块并不太影响操作,而且这种情况只有在你语音通话过程中才会出现,场景也比较特定。

UI异常原因

是什么造成这样的UI异常的,大家仔细观察就会发现在通话过程中状态栏的高度增大了20个像素,引起视图下移,进而导致UI异常。

但是大家在仔细研究一下就会发现,在使用autolayout的应用当中似乎并不太会出现这样的情况,出现这种UI异常的一般都是用frame编写UI的应用。

这是因为UIViewController的View没有设置frame的情况下自适应,当视图下移的时会将自身高度减少20个像素,保证View不超出屏幕。如果此时使用了autolayout,并且以View的边界为约束(而不是具体的数值)为约束,这样会在- (void)viewDidLayoutSubviews(在手机切换到语音通话状态时打开会后台挂起应用会触发这个方法)中使用约束重新布局,不出现异常。

我也查看了一些我们常用的APP,像微信这种界面元素比较简单的做到了比较好的通话适配,而淘宝、京东、蘑菇街之类界面元素比较复杂的应用有些地方还是有些异常,但是对于我们这些老司机也不影响正常的使用。

解决方案

这时候你也许会想,难道为了这么一个优化我们要把整个项目从frame改成autolayout(使用autolayout的小伙伴笑了),其实并不用。我写了三个宏如下:

//状态栏高度(用于通话时视图高度的适配)    
#define STATUSBARHEIGHT [[UIApplication sharedApplication] statusBarFrame].size.height
//导航高度(用户通话时视图高度的适配)
#define NAVHEIGHT ([[UIApplication sharedApplication] statusBarFrame].size.height+44)
//状态栏高度偏移(用于通话时视图高度的适配)
#define STATUSBAROFFSET ([[UIApplication sharedApplication] statusBarFrame].size.height-20)

我们在开发过程中只需要将我们常用的导航栏高度从64改成NAVHEIGHT,状态栏高度从20改成STATUSBARHEIGHT,计算状态栏高度差值时使用STATUSBAROFFSET,就可以保证你打开的新页面是自适应的。

那针对已经打开的旧页面怎么办,这就需要在上文提到的- (void)viewDidLayoutSubviews中,将和状态栏相关的frame(和这些frame相关的frame也要重新设置)重新设置一遍就好了。这样在设备接收语音通话重新打开应用后,页面就会重新layout达到自适应。

多说两句

针对这个优化,如果你使用的是frame布局,修改起来还是有一定的工作量的,个人建议在资源有限的情况下只针对一些特定的页面进行优化就好了,毕竟场景有点特殊,投入产出比不高。