AVPlayerLayer анимирует смену кадров - PullRequest
11 голосов
/ 01 июля 2011

Всякий раз, когда я меняю кадр моего AVPlayerLayer, размер видео изменяется не сразу, а анимируется до нового размера.

Например: я меняю кадр с (0, 0, 100, 100) на(0, 0, 400, 400), кадр представления немедленно изменяется, но размер видео анимируется до нового размера.

Кто-нибудь сталкивался с этой проблемой?И если да, кто-нибудь знает способ отключить анимацию по умолчанию?

Спасибо!

Ответы [ 7 ]

22 голосов
/ 02 декабря 2011

Вы можете попробовать отключить неявные действия и использовать анимацию нулевой длины:

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];
4 голосов
/ 11 августа 2016

Самый простой и чистый способ справиться с этим - создать подкласс UIView, в котором AVPlayerLayer используется в качестве layerClass. При этом AVPlayerLayer будет вести себя так же, как обычный слой UIView. Вы можете изменить кадр представления вместо слоя, и не будет никакой неявной анимации.

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

Теперь вы можете сделать это:

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

Чтобы связать AVPlayerLayer с AVPlayer, просто сделайте это:

playerLayerView.playerLayer.player = player;
4 голосов
/ 17 октября 2014

Вот что я использовал:

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

Надеюсь, это поможет.Я не знаю, если это лучшие практики, но это работает для меня.Кажется, что всякий раз, когда используются ".frame" или "setFrame", это добавляет анимацию к слою.

1 голос
/ 22 апреля 2019

Я получил эту работу в Swift 4 через следующее:

    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()
1 голос
/ 20 февраля 2017

Вот что я делаю в Swift сразу после изменения playerLayer 'frame:

playerLayer.removeAllAnimations()
1 голос
/ 17 августа 2011

Вы используете?:

- (void)setPlayer:(AVPlayer *)player {
    [(AVPlayerLayer *)[self layer] setPlayer:player];
    [(AVPlayerLayer *)[self layer] setVideoGravity:AVLayerVideoGravityResize];
}
0 голосов
/ 11 января 2016

Вероятно, это поможет в некоторых случаях:

добавление пользовательского сеттера setFrame: в поле зрения, содержащее слой игрока

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

    self.playerLayer.frame = CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height);
}
...