iOS-屏幕旋转控制总结

这段时间做的一个app,需求是大部分界面竖屏,播放器页面横屏,网页播放可横屏可竖屏。查阅了一些资料,也踩了一些坑, 在这里做一个总结。

iOS如何支持旋屏

1. project->target->Deployment Info->Device Orientation

iOS-屏幕旋转控制总结_第1张图片

这里的 Landscape LeftDevice 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中都去重写,可以选择

  1. 继承一个基类ViewController,在基类中重写上述3个方法
  2. 新建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后不横屏的情况,但是概率不高,在能接受的范围,具体原因不详,若有解决方案的朋友欢迎来交流。

你可能感兴趣的:(iOS-屏幕旋转控制总结)