如何实现AVPlayerLayer在全iOS设备上全屏显示?
Hey there! Let's get that video playing fullscreen on every device—no more weird sizing issues on iPhone 8 Plus or other models. The core problem with your current setup is that you're setting a fixed frame for the AVPlayerLayer once (in viewDidLoad), which doesn't account for different screen sizes or layout changes. Here's how to fix it step by step:
Step 1: Verify Your UIView Constraints
First, double-check the constraints for your videoUiViewOutlet (the UIView you added to hold the video):
- Make sure it has leading, trailing, top, and bottom constraints pinned directly to its parent view (the view controller's main view). This ensures the container view stretches to fill the entire screen on any device.
- If you haven't set these yet, select the UIView in Interface Builder, use the "Pin" tool to add all four edge constraints with 0 spacing.
Step 2: Update Your Code to Handle Dynamic Layouts
We need to make the AVPlayerLayer resize automatically when its container view changes size. Here's the revised code with key fixes:
import UIKit import AVFoundation import AVKit class TestViewController: UIViewController { private var player: AVPlayer! // Make playerLayer an instance variable so we can update it later private var playerLayer: AVPlayerLayer! @IBOutlet weak var videoUiViewOutlet: UIView! override func viewDidLoad() { super.viewDidLoad() self.setupView() } private func setupView() { guard let videoPath = Bundle.main.path(forResource: "clouds", ofType: "mp4"), let videoUrl = URL(fileURLWithPath: videoPath) else { print("Failed to load video file") return } let player = AVPlayer(url: videoUrl) self.player = player // Initialize playerLayer and configure it playerLayer = AVPlayerLayer(player: player) playerLayer.videoGravity = .resizeAspectFill // Ensures video fills the layer without distortion videoUiViewOutlet.layer.addSublayer(playerLayer) player.play() player.actionAtItemEnd = .none // Add notification observers NotificationCenter.default.addObserver(self, selector: #selector(videoDidPlayToEnd(notification:)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem) NotificationCenter.default.addObserver(self, selector: #selector(enteredBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(enteredForeground), name: UIApplication.willEnterForegroundNotification, object: nil) } // Override layoutSubviews to update the playerLayer's frame whenever the view resizes override func layoutSubviews() { super.layoutSubviews() playerLayer?.frame = videoUiViewOutlet.bounds } @objc func videoDidPlayToEnd(notification: Notification) { guard let playerItem = notification.object as? AVPlayerItem else { return } playerItem.seek(to: .zero, completionHandler: nil) } @objc func enteredBackground() { player.pause() } @objc func enteredForeground() { player.play() } // Clean up observers to avoid memory leaks deinit { NotificationCenter.default.removeObserver(self) } }
Key Fixes Explained:
- Instance Variable for
playerLayer: By storing the player layer as an instance variable, we can access it later to update its frame when the view resizes. layoutSubviewsOverride: This method gets called every time the view's size changes (like when rotating the device or running on a different screen size). We update the player layer's frame to match the container view's bounds here, ensuring it always fills the container.- Safer Video URL Loading: Added optional binding to handle cases where the video file might be missing, preventing crashes.
- Memory Leak Prevention: Added a
deinitmethod to remove all notification observers, which is good practice to avoid memory leaks.
Bonus: Handle Screen Rotation (Optional)
If you want to support screen rotation, make sure your view controller allows it:
- In your project settings, go to the "General" tab, under "Deployment Info", check all the device orientations you want to support.
- The
layoutSubviewsmethod will automatically handle resizing the video layer when the screen rotates, so no extra code is needed for that!
After making these changes, your video should fill the screen perfectly on every iOS device, including iPhone 8 Plus.
内容的提问来源于stack exchange,提问作者mannyCalavera

