首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS AVPlayer 自定義播放器橫豎屏切換:調整 PlayerLayer 所在 View 尺寸而非 Layer 本身

     編輯:程式設計綜合問答

AVPlayer 全屏切換時,直接修改 AVPlayerLayer.frame 或 videoGravity 會被播放器內部重置,導致畫面彈回原尺寸。正確做法是調整 承載 PlayerLayer 的 UIView 尺寸,PlayerLayer 會自動適配父視圖 bounds。

錯誤做法

// 錯誤:直接改 Layer frame,播放器內部會重置
playerLayer.frame = CGRectMake(0, 0, screenWidth, screenHeight);

正確做法

// 1. 結構:ContainerView (自動布局) → PlayerView (承載 PlayerLayer) → AVPlayerLayer
@property (nonatomic, strong) UIView *playerView; // 專門承載 layer 的 view
@property (nonatomic, strong) AVPlayerLayer *playerLayer;

// 初始化
self.playerView = [[UIView alloc] init];
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; // 或 ResizeAspectFill
[self.playerView.layer addSublayer:self.playerLayer];
// 關鍵:在 playerView layoutSubviews 中同步 layer frame
- (void)layoutSubviews {
    [super layoutSubviews];
    self.playerLayer.frame = self.playerView.bounds;
}

// 2. 全屏切換:只需調整 playerView 的 frame/constraints
- (void)toggleFullscreen:(BOOL)fullscreen {
    if (fullscreen) {
        // 移除原約束,添加全屏約束(或 frame = screenBounds)
        [self.view addSubview:self.playerView];
        self.playerView.translatesAutoresizingMaskIntoConstraints = YES;
        self.playerView.frame = [UIScreen mainScreen].bounds;
    } else {
        // 恢復原約束/frame
        [self.contentView addSubview:self.playerView];
        // 恢復 Auto Layout 約束...
    }
    // playerView.bounds 變化 → layoutSubviews → playerLayer.frame 自動同步
}

關鍵點

  1. 分離關注點:AVPlayerLayer 只負責渲染,UIView 負責佈局與動畫。
  2. Auto Layout 友好:用約束控制 playerView 尺寸/位置,旋轉、分屏、多任務自動適配。
  3. videoGravity 設置一次:AVLayerVideoGravityResizeAspect 保持比例縮放,ResizeAspectFill 裁剪填滿。
  4. 避免直接操作 Layer frame:除非在 layoutSubviews 中同步 bounds,否則播放器內部定時器會重置。

此模式適用於所有基於 CALayer 的渲染組件(如 GLKView、MTKView、WKWebView 內容層),是 iOS 視圖層級動畫佈局的核心範式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved