Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer layer inside a view does not resize when UIView frame changes

I have a UIView which contains an AVPlayer to show a video. When changing orientation, I need to change the size and location of the video.

I'm not very experienced with resizing layers, so I'm having problems making the video resize.

I start by creating the AVPlayer and adding its player to my videoHolderView's layer:

NSURL *videoURL = [NSURL fileURLWithPath:videoPath];
self.avPlayer = [AVPlayer playerWithURL:videoURL];

AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
playerLayer.frame = videoHolderView.bounds;
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
playerLayer.needsDisplayOnBoundsChange = YES;

[videoHolderView.layer addSublayer:playerLayer];
videoHolderView.layer.needsDisplayOnBoundsChange = YES;

Then, at a later point, I change the size and location of the videoHolderView's frame:

[videoHolderView setFrame:CGRectMake(0, 0, 768, 502)];

At this point, I need the avPlayer to resize to these same dimension. This doesn't happen automatically - the avPlayer stays at it's small size within the videoHolderView.

If anyone can help, I'd really appreciate any advice.

Thanks guys.

like image 263
theDuncs Avatar asked Apr 12 '12 14:04

theDuncs


3 Answers

  playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
like image 156
Markinson Avatar answered Nov 11 '22 00:11

Markinson


Converting @Suran's solution to Swift:

First, create a class inheriting UIView where you override only 1 variable:

import UIKit
import AVFoundation

class AVPlayerView: UIView {
    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}

Then add a simple UIView using the interface builder and change its class to the one you just created: AVPlayerView

change class of regular UIView to AVPlayerView

Then, make an outlet for that view. Call it avPlayerView

@IBOutlet weak var avPlayerView: AVPlayerView!

Now, you can use that view inside your viewcontroller and access its avlayer like this:

let avPlayer = AVPlayer(url: video)
let castLayer = avPlayerView.layer as! AVPlayerLayer
castLayer.player = avPlayer
avPlayer.play()

The layer will now follow the constraints just like a regular layer would do. No need to manually change bounds or sizes.

like image 39
Sam Avatar answered Nov 10 '22 22:11

Sam


Actually you shouldn't add AVPlayer's layer as a sublayer. Instead of that you should use the following method, in the subclass of view in which you want to display AVPlayer.

+ (Class)layerClass
{
     return [AVPlayerLayer class];
}

And use the following line to add(set) the player layer.

[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];

Hope it helps;-)

like image 21
Suran Avatar answered Nov 10 '22 23:11

Suran