美文网首页
4.全屏播放

4.全屏播放

作者: 豆丶浆油条 | 来源:发表于2018-08-30 20:50 被阅读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。

    相关文章

      网友评论

          本文标题:4.全屏播放

          本文链接:https://www.haomeiwen.com/subject/ywgdwftx.html