本文主要介绍POLYV iOS多场景Demo在进行iPad适配的相关知识和工作内容,包括屏幕适配、分屏适配以及处理因iPad系统版本引起的新问题。旨在让不同岗位的同学可以了解iPad适配过程。
一、屏幕适配
屏幕适配指定义一套适配规则让同一画面在iPhone以及iPad不同尺寸上按照UI设计稿呈现,也包括旋转屏幕时画面的适配。
1.1、基本原理
1.1.1 如何描述view在视图中的大小和位置:CGPoint、CGSize、CGRect、 frame 与 bounds
iOS坐标系:iOS以左上角为坐标原点(0,0),以原点向右侧为X轴正方向,原点下侧为Y轴正方向
CGPoint:iOS采用CGPoint来表示点在坐标系上X、Y位置。我们可以通过CGPointMake(x,y)来创建一个坐标点:CGPoint point = CGPointMake(80,40)
CGSize:同时,iOS采用CGSize来表示视图的宽度和高度,即视图的大小。我们可以通过CGSizeMake(width,height)来创建一个矩形的大小,如CGSize size = CGSizeMake(144,72)将创建一个宽度为144,高度为72的矩形大小。
CGRect:则是结合了CGPoint和CGSize,用来表示矩形的位置和大小。它的origin表示矩形左上角所在位置(CGPoint),size表示矩形的大小(CGSize)。
frame:描述当前视图在其父视图中的位置和大小,参照点为父视图的坐标
bounds:描述的是当前视图在本身坐标系统中的位置和大小,参照点为本身坐标系统。
1.1.2 如何布局
POLYV iOS多场景Demo屏幕适配主要layoutSubview对子视图重新布局(手动布局),也开发其他项目也会少量依靠Masonry第三方框架(自动布局)。两者的本质是一样的 都是计算坐标和宽高来实现视图的定位。
简单的对比下两者,自动布局的方法主要是通过创建约束、删除约束、重置约束来实现适配,只专注约束,依靠算法自动布局。
而使用手动布局则是通过直接设置view的frame来实现布局。layoutSubviews作为主要的实现手段是对subviews重新布局。比如,我们想更新子视图的位置的时候,可以通过调用layoutSubviews方法,即可以实现对子视图重新布局。触发时机有如下几种:
①init 不会导致layoutSubviews被调用
②addSuview 导致layoutsubview被调用在被添加视图,被添加的视图和目标的子视图(不一定是所有)
③view setFrame智能地调用视图上的layoutSubviews,只有当帧的大小参数不同时才设置帧
④滚动一个UIScrollView导致layoutSubviews被调用在scrollView和它的父视图
⑤旋转设备只调用父视图上的layoutSubview(响应的viewControllers主视图)
⑥调整视图的大小将在其父视图上调用layoutSubviews(重要:具有内在内容大小的视图将在内容决定其大小的变化时调整大小;例如,更新UILabel上的文本将导致内在内容大小被更新,从而调用其父视图上的layoutSubviews)
通过利用触发时机调用更新UI的方法以达到适配,比如下图中POLYV iOS多场景 Demo在旋转屏幕触发layoutSubview后,通过updateUI来实现布局的更新。
1.2、iPad屏幕适配实战
1.2.1 区分是否是iPad设备
在POLYV iOS多场景Demo主要依靠以下代码判断是否为iPad设备。
BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad; // iOS多场景项目中常用判断
// iphone 设备为 UIUserInterfaceIdiomPhone
#define IS_PAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) // 宏定义的方式,多场景暂时没有考虑使用
1.2.2 iPad屏幕适配实例
POLYV iOS多场景Demo设计方案iphone和iPad布局一致,因此使用同一套代码,在满足屏幕适配 基本规则时增加对iPad判断调整相应的数值即可,主要有以下几种情况:
①弹层比例不同
②页面间距不同
③控件大小不同
④显示位置不同,如iPad上居中显示
⑤列表每行展示数量不同
⑥根据设备隐藏控件
⑦占位图显示不同
二、分屏适配
分屏适配指iPad在分屏的情况下按照设计稿呈现,处理分屏旋转时引起的布局错误。
2.1 iPad分屏初了解
OS9开始,iPad开始支持split view分屏功能。
If you transition an older project to iOS 9, make your app eligible for Slide Over and Split View by ensuring your Xcode project is configured as follows:Set the Base SDK to “Latest iOS,” as described in Setting the Base SDK in App Distribution Guide.Provide a LaunchScreen.storyboard file (instead of a .png image file as you did in iOS 7 and earlier), as described in Creating a Launch Screen File in App Distribution Guide.In your project’s Info.plist file, in the “Supported interface orientations (iPad)” array, declare support for all four device orientations, as shown here:
NOTEIf you must opt out of Slide Over and Split View, do so explicitly by adding the UIRequiresFullScreen key to your Xcode project’s Info.plist file and apply the Boolean value YES. You can do this in the property list editor or in the General > Deployment Info area in the target editor.TIPA user can disable Slide Over and Split View in Settings > General > Multitasking. If you think you’ve set up everything correctly and find that these features still don’t work, check this setting.
根据官方说明可以看出如果支持分屏,需要info.plist中的“Supported interface orientations (iPad)”属性对应的值包含了四个方向,同时UIRequiresFullScreen对应的值为****NO,且需要使用LaunchScreen作为启动页。
2.2 POLYV iOS多场景Demo分屏适配实战
2.2.1 如何判断是否是分屏
在POLYV iOS多场景Demo中,主要依靠下面的方法判断是否处于分屏状态。
// 判断是否小屏
BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
Boolean isSmallScreen = viewWidth <= PLVScreenWidth / 3 ? YES : NO;
if (isPad && isSmallScreen) {}
// 判断是否是分屏
if (isPad && viewWidth == PLVScreenWidth) {}
2.2.2 POLYV iOS多场景Demo中如何体验分屏
目前云课堂观看场景支持分屏适配功能,其余场景暂时未支持。POLYV iOS多场景Demo目前默认关闭了分屏功能,也就是配置了UIRequiresFullScreen对应的值为YES,如果想体验分屏是可以配置UIRequiresFullScreen对应的值为NO。
2.2.3 云课堂分屏适配案例
在POLYV iOS多场景Demo云课堂场景中分屏时布局保持一致,在实际过程中主要是处理 控件的显示隐藏 以及分屏时控件布局的刷新。主要有以下几种情况:
①控件是否显示
②控件尺寸不同
③控制按钮的可用以及提示信息
④在编写代码时要考虑如果分屏时,需要更新哪些布局
2.2.4 iPad开启分屏引发的问题案例
2.2.4.1 开启分屏后出现打包错误
"Invalid Bundle. Your app supports Multitasking on iPad, so you must include the UILaunchStoryboardName key in your bundle, 'com.XXXXX.xxxx. Learn more
网上大部分给的解决方案是Targets - General - Deployment info - 勾选 Requires full screen。
然而如果需要你的项目需要开启分屏,那么这个解决方案和项目要求背道而驰,此时的解决方案应如下图所示,调整为launchScreen作为启动页。
2.2.4.2 开启分屏后无法限制屏幕旋转方向
开启分屏后无法限制屏幕旋转方向,也就是分屏时
系统将忽略下面两处代码:
UIApplicationDelegate中的supportedInterfaceOrientationsForWindow:方法
UIViewController通过supportedInterfaceOrientations方法设置的自己支持的屏幕方向
以及UIViewController中shouldAutorotate的值。
这可能会导致在旋转时布局出现错乱,开发过程中需要多验证旋转屏幕的情况,及时发现问题处理解决。
2.2.4.3 分屏时无法获取到相机权限
在POLYV iOS多场景Demo中,使用AVCaptureDeviceInput调用相机,而当分屏调用相机时系统要求应用具有com.apple.developer.avfoundation.multitasking-camera-access 才可以访问相机权限。这会导致分屏时,POLYV iOS多场景Demo使用相机画面黑屏。此时可以考虑使用UIImagePickerController,使用系统相机可在分屏时使用相机功能拍摄。
另外一般视频采集都使用 AVCaptureDeviceInput,例如微信视频通话、保利威的连麦功能,这都需要增加在分屏时对视频采集相关功能的禁用提醒。
更多可以访问苹果官方说明了解:https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_avfoundation_multitasking-camera-access
三 、因iPad设备引发的问题
3.1 iPadOS 13版本以上WKWebview的UserAgent变动
iPadOS 13版本以上使用WKWebview时,iPad的UserAgent会变为如下情况
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko)
这是因为在iPadOS 13版本以上新增了如下API,iPad默认的WKContentMode为WKContentModeDesktop。
typedef NS_ENUM(NSInteger, WKContentMode) {
WKContentModeRecommended,
WKContentModeMobile,
WKContentModeDesktop
} API_AVAILABLE(ios(13.0));
因此如果需要正确判断iPad设备可在configuration中设置为WKContentModeMobile。
WKWebViewConfiguration *config = [WKWebViewConfiguration new];
if (@available(iOS 13.0, *)) {
config.defaultWebpagePreferences.preferredContentMode = WKContentModeMobile;
}
_webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
四 、iPad适配总结
其实在整个iPad适配过程中,POLYV iOS多场景Demo都秉承着求同存异的理念。求同存异是指努力去寻求、扩大双方的共同点,存异就是正视并允许双方有一定的个性存在。而iPad适配也是在找寻和iPhone相同的规则 ,去判断是否为iPad适配,通过调整间距大小等方式以完成不同差异配置。
当然在开发过程中也要注意,在项目支持分屏后 对可能用到相机模块、旋转屏幕适配做好,在布局时理清各控件的关系,按照主次顺序做好布局;使用WKWebview时注意 iPadOS 13版本以上WKWebview的UserAgent变动适配。