beryllium
beryllium

Reputation: 29767

MPMoviePlayerController's view does not recognize touch

This is my code:

_mediaPlayer = [[MPMoviePlayerController alloc] init];
_mediaPlayer.controlStyle = MPMovieControlStyleNone;
_mediaPlayer.shouldAutoplay = NO;
[_mediaPlayer.view setFrame: CGRectMake(5, 5, 600,400)];
[playerHolder addSubview: _mediaPlayer.view];
//
[self prepareScreenContentToPlay];
//
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleRollTap:)];
singleFingerTap.numberOfTapsRequired = 1;
[_mediaPlayer.view addGestureRecognizer:singleFingerTap];
[singleFingerTap release];

And action method for gesture recognizer:

-(void)handleRollTap:(UITapGestureRecognizer*)sender{
    NSLog(@"%@", @"touch");
}

MPMoviePlayerController works fine. In addition I want to handle touch on MPMoviePlayerController view but handleRollTap never called. Why MPMoviePlayerController's view not works with UITapGestureRecognizer?


OK. If singleFingerTap.numberOfTapsRequired = 2; then all works fine as well. But nothing for single tap..


Upvotes: 21

Views: 13727

Answers (7)

Eran Goldin
Eran Goldin

Reputation: 979

devdavid has the right idea, but his solution didn't work for me. I guess in newer versions of the player there are other views above the movie player view.

What I did instead was add a UIView above the movie player view. This will prevent all gestures from ever getting through to the player, but that was the whole point as I didn't want any controls visible.

Upvotes: 0

Toad
Toad

Reputation: 15925

With the latest variant of the MPMoviePlayerController the accepted solution still did't work for me.

I also tried 'hacking the UIView stack', and overlaying my own UIView with gesture recognizers. But it all didn't work.

I finally implemented this solution: 'Overriding UIAplication', which seems an over the top way to do it, but in any case it works. Just add some kind of flag or delegate to it when you detect a touch event, and you can then stop the movie.

Upvotes: 0

Vaibhav Saran
Vaibhav Saran

Reputation: 12908

You can use UIView UITouch event for this. Take a UIView and put MPMoviePlayerController inside that:

theMovie = [MPMoviePlayerController new];
theMovie.view.frame = CGRectMake(0, 0, 1024, 768);
[theMovie setContentURL:theURL];
[theMovie setScalingMode:MPMovieScalingModeAspectFit];
[theMovie setCurrentPlaybackTime:0.2];
[theMovie setFullscreen:YES animated:YES];
[self addSubview:theMovie.view];
[viewMovie addSubview:theMovie.view];

Use UIView touch delegate methods

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesBegan");
    UITouch *touch = [touches anyObject];
    startPosition = [touch locationInView:self];
    [viewMovie touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touchesMoved");
    UITouch *touch = [touches anyObject];
    CGPoint endPosition = [touch locationInView:self];

    if (startPosition.x < endPosition.x)
    {
        NSLog(@"Left to Right");
    }
    else
    {
        NSLog(@"Right to Left");
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{

}

Where startPosition is a CGPoint declared in .h file.

Upvotes: 1

mdomans
mdomans

Reputation: 1303

Actually, answer to this is simple:

  • set yourself as UIGestureRecognizer delegate
  • return YES for delegate methods:

e.g.

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture)];
tapGestureRecognizer.delegate = self;

and somewhere else in the code:

#pragma mark - gesture delegate
// this allows you to dispatch touches
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
// this enables you to handle multiple recognizers on single view
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

Upvotes: 63

Horky
Horky

Reputation: 90

The root cause is the new gesture recognizer should be added on MPVideoBackgroundView, that is a subview of MPMoviePlayerController view.

Upvotes: 0

Kent Nguyen
Kent Nguyen

Reputation: 3232

Just to share my different approach for adding a custom UISwipeGestureRecognizer to the player view without adding a custom view:

[[player.view.subviews objectAtIndex:0] addGestureRecognizer:swipeGesture];

This is to replace the conventional method of calling

[player.view addGestureRecognizer:swipeGesture];

as it only works on iPad non-fullscreen mode and on iPhone. When the player goes to fullscreen mode on iPad, the gesture does not work

Upvotes: 8

devdavid
devdavid

Reputation: 1571

MPMoviePlayerController has a subview that takes up its entire bounds, and that subview has 3 gesture recognizers on it (in iOS 4.3).

mp = [[MPMoviePlayerController alloc] initWithURL:movieURL];
mp.frame = aRectangle;

for (UIGestureRecognizer *g in ((UIView *)[mp.view.subviews objectAtIndex:0]).gestureRecognizers) {
    NSLog(@"g %@", g);
}

will output:

g <MPTapGestureRecognizer: 0x6224c30; baseClass = UIGestureRecognizer; state = Possible; cancelsTouchesInView = NO; view = <MPSwipableView 0x6416100>; target= <(action=_tapGestureRecognized:, target=<MPSwipableView 0x6416100>)>>
g <UIPinchGestureRecognizer: 0x6224710; state = Possible; cancelsTouchesInView = NO; delaysTouchesEnded = NO; view = <MPSwipableView 0x6416100>; target= <(action=_pinchGestureRecognized:, target=<MPSwipableView 0x6416100>)>>
g <MPActivityGestureRecognizer: 0x6224640; baseClass = UIGestureRecognizer; state = Possible; cancelsTouchesInView = NO; delaysTouchesEnded = NO; view = <MPSwipableView 0x6416100>; target= <(action=_activityGestureRecognized:, target=<MPSwipableView 0x6416100>)>>

So there is already a GestureRecognizer that handles a single tap, but it isn't a UITapGestureRecognizer, but an MPTapGestureRecognizer (a custom recognizer for the movie player).

If you create a generic view and add it to the movie player view hierarchy, you can add touches to it, but it blocks the touches to the movie player (so a single tap won't make the controls disappear).

e.g.

UIView *aView = [[UIView alloc] initWithFrame:mp.view.bounds];
[aView addGestureRecognizer:tapGesture];
[mp.view addSubview:aView];

This will get your tap, but you break the controls. There may still be a way to allow it to interact with the other gestures.

Upvotes: 21

Related Questions