屏幕旋转之transform(视频播放器经常使用)

有个很详细的博客可以看下基础部分
https://www.jianshu.com/p/e473749f1c30

本文是在Device Orientation只勾选Portrait基础上使用transform来设置视频全屏问题

先介绍一个设备方向改变的通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationChange) name:UIDeviceOrientationDidChangeNotification object:nil];

该方法会根据设备方向的改变触发。

注:
在注册通知前需要添加以下代码:

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

文档上的定义是:

在尝试从接收器获取方向数据之前,必须调用此方法。 此方法启用设备的加速度计硬件,并开始向接收器传送加速度事件。 接收器随后使用这些事件在设备方向更改时发布UIDeviceOrientationDidChangeNotification通知并更新orientation属性。
可以安全地嵌套对此方法的调用,但是应该始终将每个调用与对endGeneratingDeviceOrientationNotifications方法的相应调用进行匹配。

因此,我们需要在dealloc方法中调用

[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];

在通知方法里获取当前设备的方向。视屏播放考虑三个方向:UIInterfaceOrientationPortrait、UIInterfaceOrientationLandscapeLeft、UIInterfaceOrientationLandscapeRight,其他方向不考虑

UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    // 未知、平放朝上、平放朝下、竖直home键朝上 不操作
    if (deviceOrientation == UIDeviceOrientationUnknown || deviceOrientation == UIDeviceOrientationFaceUp || deviceOrientation == UIDeviceOrientationFaceDown || deviceOrientation == UIDeviceOrientationPortraitUpsideDown) {
        return;
    }

    // UIDeviceOrientation转换为UIInterfaceOrientation是因为contrastOrientation:方法里进行转屏操作
    UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)deviceOrientation;
    switch (interfaceOrientation) {// 设备方向
        case UIInterfaceOrientationPortrait://屏幕竖直
        {
            [self contrastOrientation:UIInterfaceOrientationPortrait];
        }
            break;
        case UIInterfaceOrientationLandscapeLeft://屏幕左横
        {
            [self contrastOrientation:UIInterfaceOrientationLandscapeLeft];
        }
            break;
        case UIInterfaceOrientationLandscapeRight://屏幕右横
        {
            [self contrastOrientation:UIInterfaceOrientationLandscapeRight];
        }
            break;
            
        default:
            break;
    }
// 当前屏幕方向与设备方向(转化为UIInterfaceOrientation类型)对比操作
- (void)contrastOrientation:(UIInterfaceOrientation)orientation{
    // 当前状态栏方向
    UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
    
    if (currentOrientation == orientation) return;// 一致
    
  // 视频view约束+旋转
    if (orientation == UIInterfaceOrientationPortrait) {
        [self removeFromSuperview];
        [_playModel.fatherView addSubview:self];
        [self mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.playModel.fatherView);
        }];
        
    } else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight){
        [self removeFromSuperview];
        [APP_Window addSubview:self];
        
        [self mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(APP_Window);
            make.width.equalTo(APP_Window.mas_height);
            make.height.equalTo(APP_Window.mas_width);
        }];
    }
    
    /**
     * iOS6.0之后,设置状态条的方法能使用的前提是shouldAutorotate为NO,也就是说这个视图控制器内,旋转要关掉;
     UIViewController+Rotation分类写好方法
     */
    [[UIApplication sharedApplication] setStatusBarOrientation:orientation animated:NO];
    
    [UIView animateWithDuration:0.25 animations:^{
        self.transform = [self transformRotationAngle];
    }];
}


// 旋转角度
- (CGAffineTransform)transformRotationAngle{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    // 根据要进行旋转的方向来计算旋转的角度
    if (orientation == UIInterfaceOrientationPortrait) {
        return CGAffineTransformIdentity;
    } else if (orientation == UIInterfaceOrientationLandscapeLeft){
        return CGAffineTransformMakeRotation(-M_PI_2);
    } else if(orientation == UIInterfaceOrientationLandscapeRight){
        return CGAffineTransformMakeRotation(M_PI_2);
    }
    return CGAffineTransformIdentity;
}

这里有个[[UIApplication sharedApplication] setStatusBarOrientation:orientation animated:NO];,该方法是设置状态栏方向,但是iOS6.0以后有个限制条件——shouldAutorotate为NO,也就是说这个视图控制器内,旋转要关掉。

一般项目都有UITabBarController、UINavigationController、UIViewController,要修改当前ViewController的shouldAutorotate,必须在UITabBarController、UINavigationController里都要重写。

这里为了方便写了个category。(UIViewController是UINavigationController和UITabBarController父类,只要在UIViewController (Rotation)里重写shouldAutorotate可以达到效果)

UIViewController+Rotation.h

@interface UIViewController (Rotation)

@end

UIViewController+Rotation.m

@implementation UIViewController (Rotation)

// 是否支持自动转屏
- (BOOL)shouldAutorotate {
    return NO;
}

// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}


@end

这样的话,我们只需在Device Orientation只勾选Portrait就可以旋转屏幕了。

你可能感兴趣的:(屏幕旋转之transform(视频播放器经常使用))