AVPlayerLayer анимирует смену кадров

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

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

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

Спасибо!


person Alpár    schedule 01.07.2011    source источник
comment
Забавно, но у меня обратная проблема: я не могу заставить анимацию работать на AVPlayerLayer!   -  person Nicolas Miari    schedule 23.01.2020


Ответы (7)


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

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];
person djromero    schedule 02.12.2011
comment
Да вроде нормально работает. Ваше здоровье. Примечание для других: для этого требуется, чтобы QuartzCore.framework использовал CATransaction. - person Wex; 02.12.2011

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

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

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

person Atomicflare    schedule 16.10.2014
comment
Пробовал это (быстро), но поместил playerLayer.removeAllAnimations() не в то место. Вам нужно вызывать это непосредственно после каждого изменения кадра, а не при создании слоя. - person Thyselius; 11.09.2019

Самый простой и чистый способ справиться с этим — создать подкласс UIView с AVPlayerLayer в качестве класса слоя. При этом 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;
person Anton Holmberg    schedule 10.08.2016

Ты используешь ?:

- (void)setPlayer:(AVPlayer *)player {
    [(AVPlayerLayer *)[self layer] setPlayer:player];
    [(AVPlayerLayer *)[self layer] setVideoGravity:AVLayerVideoGravityResize];
}
person iTux    schedule 17.08.2011

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

playerLayer.removeAllAnimations()
person budiDino    schedule 20.02.2017

Я получил это в 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()
person JaredH    schedule 22.04.2019

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

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

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

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