转载

代码处理iOS的横竖屏旋转(下)

本文为CocoaChina网友南华coder投稿

前文链接:代码处理iOS的横竖屏旋转(上)

三、屏幕旋转方向下的视图处理

1、屏幕旋转时,建议监听UIApplicationDidChangeStatusBarOrientationNotification

原因1:supportedInterfaceOrientations方法中最终返回的是多个界面方向

原因2(最重要的原因):我们真正要处理的是页面方向发生旋转UI的变化。而在设备的物理方向发生旋转的时候,如果此时当前控制器的页面并没有旋转,我们这时改变UI布局,可能就发生问题了。

2、屏幕的宽高处理

1)在iOS 8之后,当屏幕旋转的时候,[[UIScreen mainScreen] bounds]也发生了改变。如横屏时候的屏幕宽度 其实是竖屏的时候屏幕的高度。

2)我们处理视图布局时候,如果使用到屏幕的宽高,不要直接使用SCREEN_HEIGHTSCREEN_WIDTH,而使用SCREEN_MINSCREEN_MAX

#define SCREEN_HEIGHT CGRectGetHeight([[UIScreen mainScreen] bounds])
#define SCREEN_WIDTH  CGRectGetWidth([[UIScreen mainScreen] bounds])
#define SCREEN_MIN MIN(SCREEN_HEIGHT,SCREEN_WIDTH)
#define SCREEN_MAX MAX(SCREEN_HEIGHT,SCREEN_WIDTH)

说明:竖屏时候,宽是SCREEN_MIN,高是SCREEN_MAX;横屏时候,宽是SCREEN_MAX,高是SCREEN_MIN

3、屏幕旋转下处理Demo

//监听UIApplicationDidChangeStatusBarOrientationNotification的处理
- (void)handleStatusBarOrientationChange: (NSNotification *)notification{
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    BOOL isLandscape = NO;
    switch (interfaceOrientation) {
        case UIInterfaceOrientationUnknown:
            NSLog(@"未知方向");
            break;
        case UIInterfaceOrientationPortrait:
        case UIInterfaceOrientationPortraitUpsideDown:
            isLandscape = NO;
            break;
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationLandscapeRight:
            isLandscape = YES;
            break;
        default:
            break;
    }
    if (isLandscape) {
        self.tableView.frame = CGRectMake(0, 0, SCREEN_MAX, SCREEN_MIN - 44);
    }else{
        self.tableView.frame = CGRectMake(0, 0, SCREEN_MIN, SCREEN_MAX - 64);
    }
    [self.tableView reloadData];
}

说明:当然也可以选择使用Masonry这样优秀的AutoLayout布局第三方库来处理,storyBoard来布局次之。

4、屏幕旋转下处理Demo效果图

代码处理iOS的横竖屏旋转(下)

竖屏下效果.png

代码处理iOS的横竖屏旋转(下)

横屏下效果.png

5、屏幕旋转处理的建议

1)旋转前后,view当前显示的位置尽量不变

2)旋转过程中,暂时界面操作的响应

3)视图中有tableview的话,旋转后,强制 [tableview reloadData],保证在方向变化以后,新的row能够充满全屏。

四、强制横屏

APP中某些页面,如视频播放页,一出现就要求横屏。这些横屏页面或模态弹出、或push进来。

1、模态弹出ViewController情况下 强制横屏的设置

//QSShow3Controller.m
- (BOOL)shouldAutorotate{
    return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeRight;
}
//模态弹出
QSShow3Controller *vc = [[QSShow3Controller alloc]init];
[self presentViewController:vc animated:YES completion:nil];

说明:这种情况比较简单处理。

2、push推入ViewController情况下 强制横屏的设置

//QSShow4Controller.m
-(void)viewWillAppear:(BOOL)animated{
   [super viewWillAppear:animated];
   [self setInterfaceOrientation:UIInterfaceOrientationLandscapeRight];
}
//强制转屏(这个方法最好放在BaseVController中)
- (void)setInterfaceOrientation:(UIInterfaceOrientation)orientation{
    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
        SEL selector  = NSSelectorFromString(@"setOrientation:");
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
        [invocation setSelector:selector];
        [invocation setTarget:[UIDevice currentDevice]];
        // 从2开始是因为前两个参数已经被selector和target占用
        [invocation setArgument:&orientation atIndex:2];
        [invocation invoke];
    }
}
//必须返回YES
- (BOOL)shouldAutorotate{
    return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}
//Push推入
QSShow4Controller *vc = [[QSShow4Controller alloc]init];
[self.navigationController pushViewController:vc animated:YES];

说明:苹果不允许直接调用setOrientation方法,否则有被拒的风险;使用NSInvocation对象给[UIDevice currentDevice]发消息,强制改变设备方向,使其页面方向对应改变,这是苹果允许的。

五、其他

1、 APP启动时,手机横屏下,首页UI(该页面只支持竖屏)出错(add by 2017/6/20)

//设置设置状态栏竖屏
[[UIApplication sharedApplication]setStatusBarOrientation:UIInterfaceOrientationPortrait];

以上详细源码参考:QSRotationScreenDemo

正文到此结束
Loading...