这段时间做的一个app,需求是大部分界面竖屏,播放器页面横屏,网页播放可横屏可竖屏。查阅了一些资料,也踩了一些坑, 在这里做一个总结。
iOS如何支持旋屏
1. project->target->Deployment Info->Device Orientation
这里的Landscape Left是Device Orientation,是指内容的方向,即此时手机向右旋转,home键在左边;而Landscape Right表示手机向右左旋转,home键在右边
2. 代码控制
在AppDelegate中添加方法
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAll;
}
当使用代码控制旋屏方向时,第一点的Device Orientation配置就失效了
关于旋屏之后状态栏消失的问题,解决办法是在需要旋屏的UIViewController中重写3个方法
//设置样式
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
//设置是否隐藏
- (BOOL)prefersStatusBarHidden {
return NO;
}
//设置隐藏动画
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return UIStatusBarAnimationNone;
}
如果不想在ViewController中都去重写,可以选择
- 继承一个基类ViewController,在基类中重写上述3个方法
- 新建Category
@implementation UIViewController (StatusBarCategory)
//设置样式
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
//设置是否隐藏
- (BOOL)prefersStatusBarHidden {
return NO;
}
//设置隐藏动画
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return UIStatusBarAnimationNone;
}
@end
如果风格统一,推荐第二种写法,尽量减少使用继承;若需要定制状态栏,可以使用第一种方案
那么现在来说说需要解决旋屏的需求
通常app大部分界面竖屏,有的界面强制横屏,如播放器,而有的界面支持横竖屏,如UIWebView
因为所有的旋屏都会走AppDelegate的方法
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window;
所以在AppDelegate.h暴露2个参数
@property (nonatomic, assign) BOOL allowRotate;
@property (nonatomic, assign) UIInterfaceOrientationMask interfaceOrientation;
AppDelegate.m中
//初始化参数
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.allowRotate = NO;
self.interfaceOrientation = UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return self.allowRotate?self.interfaceOrientation:UIInterfaceOrientationMaskPortrait;
}
在需要旋屏的ViewController中
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
((AppDelegate *)[UIApplication sharedApplication].delegate).allowRotate = YES;
//需要旋屏支持的方向
((AppDelegate *)[UIApplication sharedApplication].delegate).interfaceOrientation = UIInterfaceOrientationMaskLandscapeRight;
//强制旋屏
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeRight) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
((AppDelegate *)[UIApplication sharedApplication].delegate).allowRotate = NO;
//还原竖屏
((AppDelegate *)[UIApplication sharedApplication].delegate).interfaceOrientation = UIInterfaceOrientationMaskPortrait;
//强制旋屏,还原竖屏
[[UIDevice currentDevice] setValue:@(UIDeviceOrientationPortrait) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
其中比较重要的一行
[UIViewController attemptRotationToDeviceOrientation];
当你发生屏幕旋转时调用这句代码,可以解决一些奇怪的bug,比如横屏返回后,本应竖屏的界面也是横屏等。
结语
在测试当中,碰到一些问题:
- 旋屏后的手势返回问题,这个问题可以通过禁用返回手势解决
- 依然会有push后不横屏的情况,但是概率不高,在能接受的范围,具体原因不详,若有解决方案的朋友欢迎来交流。
网友评论