AVPlayerLayer animates frame changes
Asked Answered
M

7

17

Whenever I change the frame of my AVPlayerLayer, the video is not resized immediately, but animated to the new size.

For example: I change the frame from (0, 0, 100, 100) to (0, 0, 400, 400), the view's frame is changed immediately, but the video's size is animated to the new size.

Has anyone encountered this issue? And if yes does someone know a way to disable the default animation?

Thanks!

Malang answered 1/7, 2011 at 13:3 Comment(1)
Funny, I have the opposite issue: I can't get animations to work on AVPlayerLayer!Superlative
H
25

You can try disabling implicit actions and using zero length animations:

CALayer *videolayer = <# AVPlayerLayer #>
[CATransaction begin];
[CATransaction setAnimationDuration:0];
[CATransaction setDisableActions:YES];
CGRect rect = videolayer.bounds;
rect.size.width /= 3;
rect.size.height /= 3;
videolayer.bounds = rect; 
[CATransaction commit];
Hunkydory answered 2/12, 2011 at 9:31 Comment(1)
Yes, seems to work fine. Cheers. A note to others: this requires the QuartzCore.framework to use CATransactionAllium
B
8

This is what I used:

AVPlayerLayer * playerLayer = <# AVPlayerLayer #>;
playerLayer.frame = <# CGRect #>;
[playerLayer removeAllAnimations];

I hope this helps. I don't know if its best practices, but it works for me. It seems that whenever ".frame" or "setFrame" is used, it adds animation to the layer.

Bandog answered 16/10, 2014 at 22:1 Comment(1)
Tried this (in swift) but placed the playerLayer.removeAllAnimations() in the wrong place. You need to call this directly after every time you change the frame, not when you create the layer.Persist
D
4

The easiest and cleanest way to deal with this is to create a UIView subclass that has AVPlayerLayer as its layerClass. When doing this the AVPlayerLayer will behave just like a regular UIView layer. You can change the frame of the view instead of the layer and no implicit animations will happen.

AVPlayerLayerView.h

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface AVPlayerLayerView : UIView

@property (nonatomic, readonly) AVPlayerLayer *playerLayer;

@end

AVPlayerLayerView.m

#import "AVPlayerLayerView.h"

@implementation AVPlayerLayerView

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

- (AVPlayerLayer *)playerLayer {
    return (AVPlayerLayer *)self.layer;
}

@end

You can now do this:

playerLayerView.frame = CGRectMake(0, 0, 400, 400);

To associate the AVPlayerLayer with an AVPlayer simply do this:

playerLayerView.playerLayer.player = player;
Dodger answered 10/8, 2016 at 22:41 Comment(0)
G
2

Do you use ?:

- (void)setPlayer:(AVPlayer *)player {
    [(AVPlayerLayer *)[self layer] setPlayer:player];
    [(AVPlayerLayer *)[self layer] setVideoGravity:AVLayerVideoGravityResize];
}
Gantt answered 17/8, 2011 at 9:24 Comment(0)
F
2

Here is what I do in Swift right after changing the playerLayer's frame:

playerLayer.removeAllAnimations()
Fujio answered 20/2, 2017 at 11:24 Comment(0)
S
1

I got this working in Swift 4 via the following:

    var videoLayer = AVPlayerLayer()
    CATransaction.begin()
    CATransaction.setAnimationDuration(0)
    CATransaction.setDisableActions(true)
    var rect = videoLayer.bounds
    rect.size.width /= 3
    rect.size.height /= 3
    videoLayer.bounds = rect
    CATransaction.commit()
Sperling answered 22/4, 2019 at 17:40 Comment(0)
A
0

Probably this, what will help in some cases:

adding custom 'setFrame:' setter in view that holds the player layer

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];

    self.playerLayer.frame = CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height);
}
Audile answered 11/1, 2016 at 14:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.