首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ComponentKit中播放视频

在ComponentKit中播放视频
EN

Stack Overflow用户
提问于 2016-12-08 09:28:42
回答 1查看 254关注 0票数 0

我正在尝试使用ComponentKit显示视频。我想让它在点击组件时播放。我找到了这个Github Issue,所以我知道我需要使用CKStatefulViewComponent,但我不知道处理点击事件的建议方法是使用ComponentKit。

以下是我到目前为止拥有的代码:

代码语言:javascript
复制
#import "CDBVideoPlayerComponent.h"
#import <ComponentKit/ComponentKit.h>

#import <ComponentKit/CKStatefulViewComponentController.h>
#import <AVFoundation/AVFoundation.h>

@interface CDBVideoPlayerComponent()
@property (nonatomic, strong) AVPlayer *player;
@end

@implementation CDBVideoPlayerComponent

+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {

    CKComponentScope scope(self, url);

    CDBVideoPlayerComponent *component = [super newWithSize:size accessibility:{}];

    component->_player = [[AVPlayer alloc] initWithURL:url];

    return component;
}

@end

@interface CDBVideoPlayerComponentController : CKStatefulViewComponentController
- (void)handleTapForPlayer:(AVPlayer *)player;
@end

@implementation CDBVideoPlayerComponentController

+ (UIView *)newStatefulView:(id)context {

    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor darkGrayColor];

    AVPlayerLayer *playerLayer = [[AVPlayerLayer alloc] init];
    playerLayer.frame = view.bounds;

    [view.layer addSublayer:playerLayer];

    return view;
}

+ (void)configureStatefulView:(UIView *)statefulView forComponent:(CDBVideoPlayerComponent *)videoComponent {

    __block AVPlayerLayer *layer = nil;

    for (CALayer *currentLayer in statefulView.layer.sublayers) {

        if ([[currentLayer class] isSubclassOfClass:[AVPlayerLayer class]]) {
            layer = (AVPlayerLayer*)currentLayer;
            break;
        }
    }

    if (layer) {
        layer.player = videoComponent.player;
    } else {
        layer.player = nil;
    }
}

- (void)handleTapForPlayer:(AVPlayer *)player {
    [player play];
}

@end
EN

回答 1

Stack Overflow用户

发布于 2016-12-09 07:22:27

所以我找到了一个解决方案,它不是很干净,我不确定这是不是脸书的ComponentKit开发人员想要的处理这种情况的正确方式,但这个解决方案是有效的:

首先,我们需要创建一个单独的视图来处理实际的视频演示。这是从Apple's example中拉出的

代码语言:javascript
复制
#import "CDBVideoPlayerView.h"

@implementation CDBVideoPlayerView

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

- (AVPlayer*)player {
    return [(AVPlayerLayer *)[self layer] player];
}

- (void)setPlayer:(AVPlayer *)player {
    [(AVPlayerLayer *)[self layer] setPlayer:player];
}

@end

然后,组件和控制器:

代码语言:javascript
复制
#import "CDBVideoPlayerComponent.h"

#import "CDBVideoPlayerView.h"

#import <ComponentKit/CKStatefulViewComponent.h>
#import <ComponentKit/CKStatefulViewComponentController.h>
#import <AVFoundation/AVFoundation.h>

@interface CDBVideoStateComponent : CKStatefulViewComponent
@property (nonatomic, strong) AVPlayer *player;

+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size;

@end

@implementation CDBVideoStateComponent

+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {

    CKComponentScope scope(self, url);

    CDBVideoStateComponent *component = [super newWithSize:size accessibility:{}];

    component->_player = [[AVPlayer alloc] initWithURL:url];
    component->_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;

    return component;
}

@end

@interface CDBVideoStateComponentController : CKStatefulViewComponentController
@end

@implementation CDBVideoStateComponentController

+ (UIView *)newStatefulView:(id)context {

    CDBVideoPlayerView *view = [[CDBVideoPlayerView alloc] init];
    return view;
}

+ (void)configureStatefulView:(CDBVideoPlayerView *)statefulView forComponent:(CDBVideoStateComponent *)videoComponent {

    statefulView.player = videoComponent.player;
}

@end

@interface CDBVideoPlayerComponent ()
@property (nonatomic, strong) AVPlayer *player;
@end

@implementation CDBVideoPlayerComponent

+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {

    CKComponentScope scope(self, url);

    CDBVideoStateComponent *component = [CDBVideoStateComponent newWithVideoURL:url size:size];

    CDBVideoPlayerComponent *playerComponent = [super newWithComponent:component
        overlay:
        [CKButtonComponent
            newWithTitles:{}
            titleColors:{}
            images:{}
            backgroundImages:{}
            titleFont:{}
            selected:NO
            enabled:YES
            action:@selector(handleButtonPress:)
            size:{}
            attributes:{}
            accessibilityConfiguration:{}
         ]
    ];

    playerComponent->_player = component.player;

    return playerComponent;
}

- (void)handleButtonPress:(id)sender {

    if (self.player.status == AVPlayerStatusReadyToPlay) {

        if (self.player.timeControlStatus == AVPlayerTimeControlStatusPaused || self.player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
            [self.player play];
        } else {
            [self.player pause];
        }

    }
}

@end

编辑

我还发现,通过将大部分代码移到VideoPlayerView,我还发现了一种更干净的解决方案

代码语言:javascript
复制
@implementation VideoPlayerView

- (instancetype)init {

    if (self = [super init]) {
        [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]];
    }

    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {
        [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]];
    }

    return self;
}

- (void)dealloc {
    [self removeObserversForPlayer:self.player];
}

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

- (AVPlayer*)player {
    return [(AVPlayerLayer *)[self layer] player];
}

- (void)setPlayer:(AVPlayer *)player {

    [self removeObserversForPlayer:self.player];

    [(AVPlayerLayer *)[self layer] setPlayer:player];

    [self addObserverForPlayer:player];
}

- (void)addObserverForPlayer:(AVPlayer *)player {
    if (player) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
    }
}

- (void)removeObserversForPlayer:(AVPlayer *)player {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
}

- (void)itemDidFinishPlaying:(NSNotification *)notification  {
    [self.player seekToTime:kCMTimeZero];
    [self.player pause];
}

- (void)handleTap:(id)sender {

    if (self.player.status == AVPlayerStatusReadyToPlay) {

        if (self.player.timeControlStatus == AVPlayerTimeControlStatusPaused || self.player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
            [self.player play];
        } else {
            [self.player pause];
        }

    }
}

@end

更新的组件:

代码语言:javascript
复制
#import "VideoPlayerComponent.h"

#import "VideoPlayerView.h"

#import <ComponentKit/CKStatefulViewComponentController.h>
#import <AVFoundation/AVFoundation.h>
#import <ComponentKit/ComponentKit.h>

@interface VideoPlayerComponent ()
@property (nonatomic, strong) AVPlayer *player;

@end

@implementation VideoPlayerComponent

+ (instancetype)newWithVideoURL:(NSURL*)url size:(const CKComponentSize &)size {

    CKComponentScope scope(self, url);

    VideoPlayerComponent *component = [super newWithSize:size accessibility:{}];

    component->_player = [[AVPlayer alloc] initWithURL:url];
    component->_player.actionAtItemEnd = AVPlayerActionAtItemEndNone;

    return component;
}

@end

@interface VideoPlayerComponentController : CKStatefulViewComponentController
@end

@implementation VideoPlayerComponentController

+ (UIView *)newStatefulView:(id)context {

    VideoPlayerView *view = [[VideoPlayerView alloc] init];
    view.backgroundColor = [UIColor grayColor];
    return view;
}

+ (void)configureStatefulView:(VideoPlayerView *)statefulView forComponent:(VideoPlayerComponent *)videoComponent {

    statefulView.player = videoComponent.player;
}

@end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41030305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档