fix(ios): fix constraints when controls are enabled and video is inside a ScrollView (#4383)

This commit is contained in:
Efstathios Ntonas
2025-02-15 18:22:06 +02:00
committed by GitHub
parent c8b800a508
commit a8ca97f05f

View File

@@ -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)