diff --git a/ios/Video/RCTVideo.swift b/ios/Video/RCTVideo.swift index 75c5d237..4f130cf7 100644 --- a/ios/Video/RCTVideo.swift +++ b/ios/Video/RCTVideo.swift @@ -256,6 +256,14 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH name: AVAudioSession.routeChangeNotification, object: nil ) + + NotificationCenter.default.addObserver( + self, + selector: #selector(handleRotation), + name: UIDevice.orientationDidChangeNotification, + object: nil + ) + _playerObserver._handlers = self #if USE_VIDEO_CACHING _videoCache.playerItemPrepareText = playerItemPrepareText @@ -300,6 +308,28 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH return isExternalPlaybackActive } + @objc + func handleRotation() { + DispatchQueue.main.async { [weak self] in + guard let self else { return } + + self.setNeedsLayout() + self.layoutIfNeeded() + + if let playerViewController = self._playerViewController { + playerViewController.view.frame = UIScreen.main.bounds + playerViewController.view.setNeedsLayout() + playerViewController.view.layoutIfNeeded() + + // Update content overlay and subviews + playerViewController.contentOverlayView?.frame = UIScreen.main.bounds + for subview in playerViewController.contentOverlayView?.subviews ?? [] { + subview.frame = UIScreen.main.bounds + } + } + } + } + @objc func applicationWillResignActive(notification _: NSNotification!) { let isExternalPlaybackActive = getIsExternalPlaybackActive() @@ -1058,6 +1088,19 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH self._fullscreenPlayerPresented = fullscreen self._playerViewController?.autorotate = self._fullscreenAutorotate + // update layout after entering fullscreen + DispatchQueue.main.async { + self._playerViewController?.view.frame = UIScreen.main.bounds + self._playerViewController?.view.setNeedsLayout() + self._playerViewController?.view.layoutIfNeeded() + + // update content overlay subviews + self._playerViewController?.contentOverlayView?.frame = UIScreen.main.bounds + for subview in self._playerViewController?.contentOverlayView?.subviews ?? [] { + subview.frame = UIScreen.main.bounds + } + } + self.onVideoFullscreenPlayerDidPresent?(["target": self.reactTag as Any]) }) } @@ -1068,6 +1111,12 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH self?.videoPlayerViewControllerDidDismiss(playerViewController: _playerViewController) }) setControls(_controls) + + // ensure layout updates after exiting fullscreen + DispatchQueue.main.async { + self.setNeedsLayout() + self.layoutIfNeeded() + } } } @@ -1103,6 +1152,13 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH let viewController: UIViewController! = self.reactViewController() viewController?.addChild(_playerViewController) self.addSubview(_playerViewController.view) + + NSLayoutConstraint.activate([ + _playerViewController.view.leadingAnchor.constraint(equalTo: self.leadingAnchor), + _playerViewController.view.trailingAnchor.constraint(equalTo: self.trailingAnchor), + _playerViewController.view.topAnchor.constraint(equalTo: self.topAnchor), + _playerViewController.view.bottomAnchor.constraint(equalTo: self.bottomAnchor), + ]) } _playerObserver.playerViewController = _playerViewController @@ -1291,11 +1347,21 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH super.layoutSubviews() if _controls, let _playerViewController { _playerViewController.view.frame = bounds + _playerViewController.view.setNeedsLayout() + _playerViewController.view.layoutIfNeeded() + + // ensure content overlay also resizes + _playerViewController.contentOverlayView?.frame = bounds // also adjust all subviews of contentOverlayView for subview in _playerViewController.contentOverlayView?.subviews ?? [] { subview.frame = bounds } + + // ensure preferredContentSize is set when in fullscreen + if _fullscreenPlayerPresented { + _playerViewController.preferredContentSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) + } } else { CATransaction.begin() CATransaction.setAnimationDuration(0)