1

我正在尝试设置一个 NSView,它将覆盖在 AVFoundation 正在播放的视频之上。我真的只是想创建一些看起来类似于原生 quicktime 播放器的东西。我正在尝试在 OS X 应用程序上执行此操作。

我设置了一个 NSView,它有两个子视图:一个播放视频的视图和一个包含控件的视图。每当我开始播放视频时,控件视图都会被推到视频播放视图后面,从而使控件视图无用。

我认为问题与覆盖视图层次结构中同一级别的两个子视图有关。这个问题将导致使控件视图成为视频播放视图的子视图的解决方案。问题是要使用 AVFoundation 播放视频,视频播放视图必须成为图层托管视图,这会阻止它具有子视图。

我试图解决问题的事情:

  • 用于对视图addSubview:positioned:relativeTo:重新排序。
  • 支持超级视图和控件视图层。

我可能错误地使用了这些解决方案,所以如果您认为它们应该起作用,请告诉我。

这就是我设置视频播放视图的方式。

self.playerItem = [AVPlayerItem playerItemWithAsset:self.asset];
[self.playerItem addObserver:self forKeyPath:@"status"
             options:0 context:&ItemStatusContext];
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];

self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];

[self.playerView setLayer:self.playerLayer];
[self.playerView setWantsLayer:YES];

这似乎是某人想要为视频播放做的常见事情,所以如果有人知道解决方案,请告诉我。谢谢!

4

1 回答 1

2

请注意,文档并没有说图层托管视图不能包含任何子视图,他们只是说您不能将任何子视图添加到图层托管视图。您可以先将所需的所有子视图添加到视图中,然后将其转换为图层托管视图。然而,即使在这种情况下,层和子视图的顺序也不是确定性的。

我通过在我的主视图中创建两个子视图解决了这个问题。其中一个子视图是分层托管的,并具有视频播放层;另一个子视图是包含控件的图层支持视图。这是我解决这个问题的方法:

   [self setWantsLayer:YES]; // Turn your main view into a layer backed view, so ordering of subviews is deterministic.

    _controlsView = [[NSView alloc]initWithFrame:frame];        
    _playButtonOverlay = [[NSImageView alloc] initWithFrame:frame];
    [ _playButtonOverlay setImage:[NSImage imageNamed:@"play_overlay"]];
    [_controlsView addSubview:_playOverlay];

    _videoView = [[NSView alloc]initWithFrame:frame];
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];        
    [_videoView setLayer:_playerLayer]; // make this subview layer-hosted
    [_videoView setWantsLayer:YES];
    [self insertSubview:_videoView belowSubview:_controlsView];

如果您还没有,请参阅 NSView 中的 setWantsLayer 文档。它说:

“支持层的视图是由核心动画层支持的视图。视图完成的任何绘制都缓存在支持层中。您可以通过调用 setWantsLayer: 值来配置支持层的视图:值为 YES。

“图层托管视图是包含您打算直接操作的核心动画层的视图。您通过实例化核心动画图层类并将该图层提供给视图的 setLayer: 方法来创建图层托管视图。这样做之后,然后调用 setWantsLayer: 值为 YES。此方法顺序至关重要。

于 2013-08-16T23:23:43.390 回答