美文网首页
横竖屏的记录

横竖屏的记录

作者: limbo_lyn | 来源:发表于2018-12-18 16:57 被阅读0次

    需求:

    在TableViewCell中播放视频,根据设备横竖屏切换自动全屏或小窗口播放

    错误的解决方案:

    按照常规的做法,第一想法,就是监听旋转屏幕的方法,在旋转屏幕事件中对播放器进行操作。

    实现如下,在当前UIViewController的根UIViewController(UINavigationController或者UITabBarController)进行旋转控制,代码如下

    一、根UIViewController

    1、声明变量

     var orientationMask = UIInterfaceOrientationMask.portrait    

      var autorotate = false 

      var hiddenStatusBarIfNeed = false 

    2、声明控制函数

     override var supportedInterfaceOrientations:UIInterfaceOrientationMask{

            return orientationMask

        }

      override var prefersStatusBarHidden:Bool{

            return hiddenStatusBarIfNeed

        }

      override var shouldAutorotate:Bool{

            return autorotate

        }

    二、在播放视频的UIViewController中

    1、播放时打开根UIViewController的旋转开关

    open func shouldRotate() {

            let landscapeController = navigationController as? LandscapeNavigatonController

            if landscapeController == nil {

                return

            }

            if videoPlayer.isPlaying  {

                landscapeController!.autorotate = true

                landscapeController!.orientationMask = .allButUpsideDown

            } else {

                landscapeController!.autorotate = false

                landscapeController!.orientationMask = .portrait

            }

        }

    2、监听事件,对player进行操作(主要是调整player大小)

            NotificationCenter.default.addObserver(self,

                                                   selector:#selector(onOrientationChanged),

                                                   name:NSNotification.Name.UIApplicationDidChangeStatusBarOrientation,

                                                   object:nil)

    问题:

    看似一切都没有问题,但是运行的时候,由于UIViewController旋转,导致UITableView会调用reloadData方法,而横竖屏幕的高度不一样,有可能导致会调用到UITableView的didEndDisplaying方法(这个方法中我们应该停止播放视频),所以这个方法不行


    正确的解决方案:

    我们只需要知道屏幕是否旋转,在旋转中对player进行操作即可,并不需要将整个UIViewController进行旋转,这样就不会调用到reloadData方法。实现方法如下:

    1、关闭根UIViewController的旋转开关

    2、监听设备旋转事件

    3、对player进行旋转

     weakself?.mediaPlayer.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 2))

    即可,关键代码:

    func handleVideoFullScreen(deviceOrientation: UIDeviceOrientation) {

            weak var weakself = self

            let duration = 0.75

            switch deviceOrientation {

            case .portrait, .portraitUpsideDown:

                playerControlView.showBackButton.isHidden = true

                if let playerFrame = defaultPlayerFrame {

                    mediaPlayer.removeFromSuperview()

                    defaultPlayerSuperView?.addSubview(mediaPlayer)

                    UIView.animate(withDuration: duration) {

                        weakself?.mediaPlayer.transform = CGAffineTransform(rotationAngle: 0);

                        weakself?.mediaPlayer.frame = playerFrame

                        weakself?.defaultPlayerFrame = nil

                    }

                    UIApplication.shared.setStatusBarHidden(false, with: .fade)

                    UIApplication.shared.statusBarOrientation = .portrait

                }

            case .landscapeLeft:

                playerControlView.showBackButton.isHidden = false

                defaultPlayerSuperView = mediaPlayer.superview

                defaultPlayerFrame = mediaPlayer.frame

                // 获取相对坐标值

                mediaPlayer.removeFromSuperview()

                UIApplication.shared.setStatusBarHidden(false, with: .fade)

                UIApplication.shared.statusBarOrientation = .landscapeRight

                let frame = self.view.convert(mediaPlayer.frame, from: playingCell)

                mediaPlayer.frame = frame

                let keyWindow = UIApplication.shared.keyWindow

                keyWindow?.addSubview(mediaPlayer)

                UIView.animate(withDuration: duration) {

                    weakself?.mediaPlayer.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 2))

                    weakself?.mediaPlayer.frame = CGRect(x: 0, y: 0, width: screenHeight, height: screenWidth)

                }

            case .landscapeRight:

                playerControlView.showBackButton.isHidden = false

                defaultPlayerSuperView = mediaPlayer.superview

                defaultPlayerFrame = mediaPlayer.frame

                mediaPlayer.removeFromSuperview()

                UIApplication.shared.setStatusBarHidden(false, with: .fade)

                UIApplication.shared.statusBarOrientation = .landscapeRight

                let frame = self.view.convert(mediaPlayer.frame, from: playingCell)

                mediaPlayer.frame = frame

                let keyWindow = UIApplication.shared.keyWindow

                keyWindow?.addSubview(mediaPlayer)

                UIView.animate(withDuration: duration) {

                    weakself?.mediaPlayer.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi / 2))

                    weakself?.mediaPlayer.frame = CGRect(x: 0, y: 0, width: screenHeight, height: screenWidth)

                }

            default:

                break

            }

        }

    其他相关的点

    1、只有一个Player,当用户点击播放的时候,把Player加入到cell中播放,当全屏的时候,把Player加入到UIApplication.shared.keyWindow中旋转

    2、全屏时,需要把player的在Cell的坐标转化为UIApplication.shared.keyWindow的坐标系

    let frame = UIApplication.shared.keyWindow!.convert(mediaPlayer.frame, from: playingCell)

    3、Cell被移除屏幕后停止播放,在didEndDisplaying方法中处理

    相关文章

      网友评论

          本文标题:横竖屏的记录

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