AVPlayer UITapGestureRecognizer不起作用

10

我有一个针对我的 AVPlayerViewController 的代码。

UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAvPlayer)];
[self.avPlayerViewController.view addGestureRecognizer:tap];
但这不起作用... :S,我尝试设置

[self.avPlayerViewController.view setUserInteractionEnabled:YES];

依然不好...

唯一可行的解决方案是使用 UIGestureRecognizer 并实现它的 shouldReceiveTouch 代理并检查是否触摸了 AV 播放器.. 但问题是,我们想要捕获“松开点击”事件.. 因为如果仅仅点击了AV播放器视图,它会立即执行代码,这不是我们想要的...

请帮助我们解决这个问题..

谢谢!

8个回答

8

在AVPlayerViewController中处理手势的正确位置是在控制器的contentOverlayView内。

contentOverlayView是AVPlayerViewController的只读属性。它是一个显示在视频上方但在控制器下方的视图。正是触摸处理的完美位置。您可以在加载时向其添加子视图或手势处理程序。

以下代码提供了两种方式为您的视频控制器提供触摸支持,以演示手势识别和UIButton方法。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"mySegue"])
    {
        // Set things up when we're about to go the the video
        AVPlayerViewController *avpvc = segue.destinationViewController;
        AVPlayer *p = nil;
        p = [AVPlayer playerWithURL:[NSURL URLWithString:@"https://my-video"]];
        avpvc.player = p;

        // Method 1: Add a gesture recognizer to the view
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(myAction:)];
        avpvc.contentOverlayView.gestureRecognizers = @[tap];

        // Method 2: Add a button to the view
        UIButton *cov = [UIButton buttonWithType:UIButtonTypeCustom];
        [cov addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
        cov.frame = self.view.bounds;
    }
}

目前暂时不准备编写Swift版本,抱歉。 :)


我有一个AVPlayerViewController,负责在自定义的UITableViewCell中播放视频。将手势识别器添加到“contentOverlayView”的方法似乎不起作用。一旦播放器视图添加到单元格中,某种方式会拦截触摸。您对如何解决此问题有什么想法吗?谢谢! - Stoph
@Stoph,你最终找到解决方案了吗? - Zigii Wong
@ZigiiWong,我不得不返回并查找我的代码,但我确实找到了解决方案。我最终创建了一个自定义的AVPlayerViewController子类,并覆盖了- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event方法。覆盖方法调用了一个自定义代理接口,该接口摄取触摸事件以执行我需要的任何操作。 - Stoph
将识别器添加到.contentOverlayView对我没有起作用(从未收到回调),但是avpvc.view.gestureRecognizers = @[tap]起了作用。 - eddybox

5
这应该就行了。将识别器添加到播放器的子视图中即可:
[videoPlayerViewController.view.subviews[0] addGestureRecognizer:tap]

这是一个针对复杂UI和手势的快速解决方案,请查看contentOverlayView以获取更多信息。请参考TyR的回答。

我试了一个星期才让它工作,结果只需要这么简单的一步。太棒了!谢谢你,你真的救了我。 - user3286381
5
在iOS 11上,这会导致应用程序崩溃。 - Andrea Mario Lufino
iOS 11仍处于测试版,稍后会查看。 - Radu
2
有人能确认最终版本11还会崩溃吗? - sigi
2
使用了未记录的SPI。首选的方法是使用contentOverlayView(请参见我的答案)。 - TyR
1
在iOS 12上,这会导致应用程序崩溃。 - Will

0

您可以在AVPlayerViewController上添加一个transparent视图,并在该视图上添加tapgesturerecognizer手势识别器。希望这能帮到您 :)


0

简单的解决方案是在添加电影播放器后,在同一电影容器视图上添加手势视图。 无需直接将手势识别器添加到电影播放器中。

  [self.movieHolderView addSubview:self.moviePlayer.view];


  [self.movieHolderView addSubview:self.gestureView];
  [self.movieHolderView bringSubviewToFront:self.gestureView];

现在我们可以像这样在手势视图上添加手势识别器。
self.fullScreenTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapHandler:)];
self.fullScreenTapGesture.numberOfTapsRequired = 1;
[self.gestureView addGestureRecognizer:self.fullScreenTapGesture];

0

就我所知,您真正想要的是

UILongPressGestureRecognizer

因为,

UITapGestureRecognizer

没有任何发布类型的事件,如果您添加了

UILongPressGestureRecognizer

到你的

avPlayerViewController

然后在

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  if ( [gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] ) {

  }
  return YES;
}

然后您可以设置手势的最短持续时间,以获得更好的体验。

[holdGesture setMinimumPressDuration:0.01]

然后你可以实现这个方法,

- (void)holdAction:(UILongPressGestureRecognizer *)holdRecognizer

然后检查识别器的状态并执行所需功能


0
Swift 4
在AVPlayerViewController的视图中添加手势识别器:
func playVideo() {
    let playerController = AVPlayerViewController()
    playerController.player = AVPlayer(url: URL(fileURLWithPath: videoPath))
    playerController.showsPlaybackControls = false
    playerController.view.isUserInteractionEnabled = true

    let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
    swipeUp.direction = UISwipeGestureRecognizerDirection.up
    playerController.view.addGestureRecognizer(swipeUp)

    present(playerController, animated: false) {
        playerController.player?.play()
    }
}

@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
    print("swipe up")
}

0

针对OS11和早期OS应分别添加手势识别器:

通用解决方案(Swift 4):

let tap = UITapGestureRecognizer(target: self, action: #selector(videoTap))

if #available(iOS 11.0, *) {
    playerVC?.contentOverlayView?.gestureRecognizers = [tap]
} else {
    playerVC?.view.subviews.first?.addGestureRecognizer(tap)
}

@objc func videoTap(_ button: UIButton) {
    print("Tapped on video")
}

-1

或者您可以子类化AVPlayerViewController并使用以下方法来获取控制权:

- 获取控制权:

1.touchBegan 2.touchEnd

请确保设置此标志 self.avPlayerContr.showsPlaybackControls = false

希望这对您有用。


1
覆盖UIControl方法是一个hack。优先选择使用contentOverlayView(请参见我的答案)。 - TyR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接