4.全屏播放

2018-08-30  本文已影响35人  豆丶浆油条

  全屏播放是每一个视屏播放器的标配。切换横竖屏有两种方式,视频播放器的画面随着手机的旋转而旋转和点击按钮切换。我们先将第一种方式,所以必须要监测手机的旋转。
  监测手机的旋转很简单,苹果通过通知的方式告诉我们。

 // 开启监听设备旋转的通知(不开启的话,设备方向一直是UIInterfaceOrientationUnknown)
    // ioS11.4.1 不开启也能检测到
    if (![UIDevice currentDevice].generatesDeviceOrientationNotifications) {
        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    }
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

deviceOrientationDidChange是回调方法,设备只要发生旋转就会调用这个方法。

- (void)deviceOrientationDidChange:(NSNotification *)noti
{
    // 设备方向
    UIInterfaceOrientation deviceOrientation =(UIInterfaceOrientation)[[UIDevice currentDevice] orientation];
    // 界面方向
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (deviceOrientation == interfaceOrientation || !UIDeviceOrientationIsValidInterfaceOrientation(deviceOrientation)) {
        NSLog(@"UIDeviceOrientationUnknown");
        return;
    }
    
    [self changeInterfaceOrientation:deviceOrientation];
}

[[UIDevice currentDevice] orientation];返回的是设置的方向,值的类型是UIDeviceOrientatin`,它是一个枚举,一个有7个值。

typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
    UIDeviceOrientationUnknown,          // 未知
    UIDeviceOrientationPortrait,            //  竖屏,HOME键在下面
    UIDeviceOrientationPortraitUpsideDown,  // 竖屏,HOME键在上面
    UIDeviceOrientationLandscapeLeft,       // 横屏,HOME键在左面
    UIDeviceOrientationLandscapeRight,      // 横屏,HOME键在右面
    UIDeviceOrientationFaceUp,              // 平放,屏幕朝上
    UIDeviceOrientationFaceDown             // 平放,屏幕朝下
} 

需要注意的是屏幕横放的时候,是不能区分横竖屏的。[[UIApplication sharedApplication] statusBarOrientation];返回值是界面的方向,类型是UIInterfaceOrientation,也是一个枚举值,一共有5个值。

    UIInterfaceOrientationUnknown,   // 未知
    UIInterfaceOrientationPortrait ,     //  竖屏,HOME键在下面
    UIInterfaceOrientationPortraitUpsideDown,  // 竖屏,HOME键在上面
    UIInterfaceOrientationLandscapeLeft, // 横屏,HOME键在左面
    UIInterfaceOrientationLandscapeRight   // 横屏,HOME键在右面

我们监听到手机旋转后,第一步要检验一下设备的方向是否可以转化为有效的界面方向。UIDeviceOrientationIsValidInterfaceOrientation(deviceOrientation)。因为如果是UIDeviceOrientationUnknown、UIDeviceOrientationFaceUp、UIDeviceOrientationFaceDown,我们没办法分清横竖屏,就没办法旋转界面的方向。第二步判断两种方向是否一致,不一致在旋转。

// 旋转屏幕,interfaceOrientation要旋转的方向
- (void)changeInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // 父视图
    UIView *superView = nil;
    // 旋转的角度,默认值是恢复原来的样式
    CGAffineTransform  transform = CGAffineTransformIdentity;
    
    // 竖屏 -> 横屏
    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        // 父视图是keyWindow
        superView = [[UIApplication sharedApplication] keyWindow];
        
        // HOME键在左边,逆时针旋转90°
        if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
            transform = CGAffineTransformMakeRotation(-M_PI_2);
            
        }else if(interfaceOrientation == UIInterfaceOrientationLandscapeRight){
             // HOME键在右边,顺时针旋转90°
            transform = CGAffineTransformMakeRotation(M_PI_2);
        }
        // 记录界面的状态
        self.isFullScreen = YES;
        
    }else{
        // 横屏 -> 竖屏
        superView = self.containerView;
        transform = CGAffineTransformIdentity;
        self.isFullScreen = NO;
    }
    
    [superView addSubview:self.presentView];
    
    // 修改界面的方向
    [UIApplication sharedApplication].statusBarOrientation = interfaceOrientation;
    // 标记界面的方向需要更改
    [self setNeedsStatusBarAppearanceUpdate];
    
    // 旋转动画
    [UIView animateWithDuration:0.25 animations:^{
        // 旋转
        self.presentView.transform = transform;
        [UIView animateWithDuration:0.25 animations:^{
            // 修改尺寸
            self.presentView.frame = superView.bounds;
        }];
    }  completion:^(BOOL finished) {
        // 修改控制视图的约束
        [self updateControlViewConstraint];
    }];
}

- (void)updateControlViewConstraint
{
    // 当屏幕旋转后,屏幕的长宽也发生了变化,现在长的值变为了原来的宽的值
    if (self.isFullScreen) {
        CGFloat width = self.presentView.bounds.size.width;
        CGFloat height = self.presentView.bounds.size.height;
        self.controlView.frame = CGRectMake(0, height - 40, width, 40);
    }else{
        CGFloat width = SCREEN_WIDTH;
        CGFloat height = SCREEN_WIDTH / 7 * 4;
        self.controlView.frame = CGRectMake(0, height - 40, width, 40);
    }
    
    // 如果不执行下面的两个方法, 上面的设置无效
    // 标记更新约束
    [self.controlView setNeedsUpdateConstraints];
    // 更新约束
    [self.controlView updateConstraintsIfNeeded];
    
}

  当横屏的时候,presentView(layer是AVPlayerLayer,视频播放器的界面)的父视图的就变成了keyWindow。我们选择界面的时候,也需要修改statusBarOrientation的值,[UIApplication sharedApplication].statusBarOrientation = interfaceOrientation;。因为还要和设备的方向做比较。
  你以为上面的方法执行完之后,就能横竖屏切换了嘛?当然不是,结尾有彩蛋奥。执行方上面的方法,可以由竖屏转化为横屏,确转化不回来了。因为[UIApplication sharedApplication].statusBarOrientation = interfaceOrientation;这个方法设置无效,[UIApplication sharedApplication].statusBarOrientation的值一直是UIDeviceOrientationPortrait。当设备由横屏转化为竖屏的时候,设备的方向和屏幕的方向分别是UIDeviceOrientationPortrait和UIInterfaceOrientationPortrait是相等的,所以不会执行旋转的方法。所以我们还要加一个方法。

// 界面是否可以跟随手机自动旋转
// if yes, [UIApplication sharedApplication].statusBarOrientation = deviceOrientation; 设置无效;
// if yes, - (UIInterfaceOrientationMask)supportedInterfaceOrientations;支持的屏幕方向一定要和Deployment Info -> Device Orientation 一致, 否则会报  Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and [FHNavigationController shouldAutorotate] is returning YES'
- (BOOL)shouldAutorotate {
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    if (self.isFullScreen) {
        return UIInterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskPortrait;
}

这个方法shouldAutorotate默认返回YES,表明界面可以随着视频自动旋转,不要我们设置什么了。那当然不行,那样UI就会乱,大家可以试一试。所以我们要返回NO,由我们自己控制界面的旋转supportedInterfaceOrientations返回的是界面支持的旋转方向,返回值得类型是UIInterfaceOrientationMask。

上一篇下一篇

猜你喜欢

热点阅读