MpMovieplayerController tap gesture recognizer doesn't trigger when in fullscreen - ios

I´m trying to use UITapGestureRecognizer in order to handle the taps on my fullscreen video. If I omit [self.player setFullscreen:YES animated:NO]; it works, but then my video won't scale to fit the screen.
From my .m:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *videoPath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"mov"];
player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:videoPath]];
player.shouldAutoplay = NO;
player.view.frame = self.view.bounds;
player.scalingMode = MPMovieScalingModeAspectFit;
player.controlStyle = MPMovieControlStyleNone;
player.fullscreen = YES;
self.player = player;
[self.player prepareToPlay];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
UIView *aView = [[UIView alloc] initWithFrame:player.view.bounds];
[aView addGestureRecognizer:tapGesture];
[self.player.view addSubview:aView];
}
- (IBAction)playMovie:(id)sender {
//add the MPMoviePlayerViewController to this view (as subview)
//Play movie
[self.view addSubview:self.player.view];
[self.player setFullscreen:YES animated:NO]; //commenting out this will make it work
[self.player play];
}
- (void)handleTap:(UITapGestureRecognizer *)recognizer {
NSLog(#"tap tap");
}
From my .h:
#property (retain, nonatomic) MPMoviePlayerController *player;
- (void)handleTap:(UITapGestureRecognizer *)recognizer;

You can try this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(willEnterFullScreen:)
name:MPMoviePlayerWillEnterFullscreenNotification
object:nil];
- (void)willEnterFullScreen:(NSNotification*)notification
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
UIView *aView = [[UIView alloc] initWithFrame:self.player.backgroundView.bounds];
[aView addGestureRecognizer:tapGesture];
[self.view.window addSubview:aView];
}
and then remove your subview when MPMoviePlayerWillExitFullscreenNotification is posted

In my comment, I drafted how to get that covered when using proper fullscreen ([self.player setFullscreen:YES animated:NO];).
I would suggest that instead you simply resize the player view to cover the entire screen by setting its frame accordingly.
You initialising code would have to get rid of that player.fullscreen = YES;, but that I guess is obvious by now.

Related

How to add an overlay to a AVPlayer?

I want to play a video in AVPlayer but want to open the AVPlayer in a UIView so that I can add a overlay on it.
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:#"Play" forState:UIControlStateNormal];
[button sizeToFit];
button.center = CGPointMake(320/2, 60);
[button addTarget:self action:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
-(void)buttonPressed:(UIButton *)button
{
NSURL *urlVideoFile = [NSURL fileURLWithPath:#"https://www.rmp-streaming.com/media///bbb-360p.mp4"];
NSAssert(urlVideoFile, #"Expected not nil video url");
_playerViewController = [[AVPlayerViewController alloc] init];
_playerViewController.player = [AVPlayer playerWithURL:urlVideoFile];
_playerViewController.view.frame = self.view.bounds;
_playerViewController.showsPlaybackControls = YES;
[self.view addSubview:_playerViewController.view];
self.view.autoresizesSubviews = YES;
}
It's playing the video in a player, but I want to open the video in a UIView so that I can add the overlay on it.
Take IBOutlet of Your UIView for Example
IBOutlet UIView *videoView;
And Call this method
-(void)buttonPressed:(UIButton *)button
{
NSURL *videoURL = [NSURL fileURLWithPath:filePath];
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
playerLayer.frame = videoView.bounds;
[videoView.layer addSublayer:playerLayer];
[player play];
player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[player currentItem]];
}
- (void)playerItemDidReachEnd:(NSNotification *)notification
{
AVPlayerItem *p = [notification object];
[p seekToTime:kCMTimeZero];
}

UISwipeGestureRecognizer Not Performing Method

I am having a difficult time getting a Swipe Gesture Recognizer to work on my app. Here is the Hierarchy of it all.
App's root view is a UINavigationController which has class ViewController as visible for the first view seen. I have a UIButton which will fire a movie that loops until I tap it twice which will have the navigation controller push a new ViewController that I have made called PUPPETS1 onto the screen. This VC has its own xib. The xib has a UIImageView. What I want to have happen is to start playing a movie once I swipe up on the screen, but that never happens, and the console never shows my NSLog from the 2nd VC's method.
- (void)loopVideo {
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:#"warpspeed" withExtension:#"mov"];
UIView *patternView = [[UIView alloc] initWithFrame:self.view.bounds];
patternView.backgroundColor = [UIColor blackColor];
[self.moviePlayer2.backgroundView addSubview:patternView];
self.moviePlayer2 = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[self.moviePlayer2 setControlStyle:MPMovieControlStyleDefault];
self.moviePlayer2.controlStyle = MPMovieControlStyleNone;
self.moviePlayer2.scalingMode = MPMovieScalingModeAspectFill;
self.moviePlayer2.movieSourceType = MPMovieSourceTypeFile;
[self.moviePlayer2 setAllowsAirPlay:YES];
self.moviePlayer2.view.frame = self.view.frame;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(puppetOne)];
tapGesture.numberOfTapsRequired = 2;
tapGesture.numberOfTouchesRequired = 1;
UIView *aView = [[UIView alloc] initWithFrame:self.moviePlayer2.backgroundView.bounds];
[aView addGestureRecognizer:tapGesture];
[self.view.window addSubview:aView];
[self.view addSubview:self.moviePlayer2.view];
self.moviePlayer2.repeatMode = MPMovieRepeatModeOne;
[self.moviePlayer2 play];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
In the 2nd VC, the PUPPETS1 one:
- (void)viewDidLoad {
[super viewWillAppear:YES];
UISwipeGestureRecognizer * swipeRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(playPuppets)];
swipeRec.direction = UISwipeGestureRecognizerDirectionUp;
UIView *aView2 = [[UIView alloc] initWithFrame:self.view.bounds];
[aView2 addGestureRecognizer:swipeRec];
[self.view addSubview:aView2];
// Do any additional setup after loading the view from its nib.
}
-(void)playPuppets {
NSLog(#"PLAYING");
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:#"SundayPuppets" withExtension:#"m4v"];
//filePath may be from the Bundle or from the Saved file Directory, it is just the path for the video
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
AVPlayerViewController *playerViewController = [AVPlayerViewController new];
playerViewController.player = player;
//[playerViewController.player play];//Used to Play On start
[self presentViewController:playerViewController animated:YES completion:nil];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
The frame of the view to which you're attaching the gr depends on it's parent view's bounds, and those aren't initialized yet in viewDidLoad.
Move the setup to after layout is complete (and tweak it to run just once, on the first layout change), i.e.
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIView *swipeView = [self.view viewWithTag:999];
// only do this if we haven't done it already
if (!swipeView) {
// now that self.view.bounds is initialized...
swipeView = [[UIView alloc] initWithFrame:self.view.bounds];
swipeView.tag = 999;
// the rest of your OP setup code is fine, and goes here
UISwipeGestureRecognizer * swipeRec = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(playPuppets)];
swipeRec.direction = UISwipeGestureRecognizerDirectionUp;
[swipeView addGestureRecognizer:swipeRec];
[self.view addSubview:swipeView];
NSLog(#"%#", swipeView);
}
}
EDIT The code above attached the gesture recognizing view correctly, providing a fix in the second view controller. It turns out that the other problem was the previous view controller was not properly removing the (deprecated) MPMoviePlayer, resulting in touches not functioning on the pushed vc. The entire reworked ViewController.m can be found in the chat linked below, but the fix for the touches issue was here...
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.moviePlayer stop];
[self.moviePlayer.view removeFromSuperview];
self.moviePlayer = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

UISlider added on AVPlayerViewController contentOverlayView is not responding

I am trying to add a UISlider to control volume in AVPlayerViewController, for this i have added a UISlider on 'AVPlayerViewController.contentOverlayView'. UISlider is not allowing me to drag as if it is not enabled and its selector action method 'changeVolumeLevelOfPlayer' is not getting called.
Here is my code:
-(void)viewDidLoad {
[super viewDidLoad];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
AVPlayerViewController *avPlayerViewController = [[AVPlayerViewController alloc] init];
AVPlayer *player = [AVPlayer playerWithURL:[self getVideoURLAtIndex:[self.indexOfCurrentTrailer intValue]]];
avPlayerViewController.player = player;
avPlayerViewController.delegate = self;
[player play];
avPlayerViewController.view.frame = CGRectMake(0, 0, 300, 250);
UISlider *sliderForVolumeControl = [[UISlider alloc] initWithFrame:CGRectMake(0, avPlayerViewController.view.frame.size.height/2, 100, 40)];
[sliderForVolumeControl setMinimumValue:0.0];
[sliderForVolumeControl setMaximumValue:1.0];
[sliderForVolumeControl setValue:0.5];
sliderForVolumeControl.continuous = YES;
[sliderForVolumeControl setBackgroundColor:[UIColor orangeColor]];
[sliderForVolumeControl addTarget:self action:#selector(changeVolumeLevelOfPlayer:) forControlEvents:UIControlEventValueChanged];
[sliderForVolumeControl setUserInteractionEnabled:YES];
[sliderForVolumeControl setEnabled:YES];
[avPlayerViewController.contentOverlayView addSubview:sliderForVolumeControl];
[self addChildViewController:avPlayerViewController];
[self.view addSubview:avPlayerViewController.view];
[avPlayerViewController didMoveToParentViewController:self];
[player addObserver:self forKeyPath:#"status" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:nil];
}
-(void)changeVolumeLevelOfPlayer:(UISlider *)sender {
player.volume = sender.value;
}
From the apple docs:
Use the content overlay view to add additional custom views between
the video content and the controls.
So it looks like this: (with a bunch of other layers over your UISlider)
To make it work just change this line:
[avPlayerViewController.contentOverlayView addSubview:sliderForVolumeControl];
to this:
[avPlayerViewController.view addSubview:sliderForVolumeControl];

MPMoviePlayerController not recognizing UITapGestureRecognizer

I'm trying to add a UITapGestureRecognizer to my MPMoviePlayerController, like this:
- (void)playVideo {
NSString *videoURL = self.post[#"videos"][#"high_resolution"];
videoURL = [videoURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:videoURL];
self.videoURL = url;
self.videoController = [[MPMoviePlayerController alloc] init];
self.videoController.controlStyle = MPMovieControlStyleNone;
self.videoController.backgroundView.backgroundColor = [UIColor clearColor];
[self.videoController setContentURL:self.videoURL];
[self.videoController.view setFrame:CGRectMake (0, 0, 320, 320)];
[_sharedImage addSubview:self.videoController.view];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playy)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.videoController];
self.playBtn.hidden = YES;
[self.videoController play];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[_videoController.view addGestureRecognizer:tap];
}
- (void)handleTap:(UITapGestureRecognizer *)gesture {
[_videoController pause];
NSLog(#"Video was tapped");
}
#pragma mark - Gesture Delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
But the MPMoviePlayerController seems not to recognize the tap gesture, and nothing happens when I tap the video. Please explain this. Thanks!
You should set disabled interactions like so...
self.videoController.userInteractionEnabled = false;
Then add your gesture to the superview instead
[self.view addGestureRecognizer:tap];
It seems that you are missing one important line:
tap.delegate = self;
delegates won't be called if you don't set it

Adding a UITapGestureRecognizer to MPMoviePlayerController

Nothing happens when I tap on my MPMoviePlayerController. Can anyone see what I am doing wrong in setting up the UITapGestureRecognizer?
- (void) playMovie : (NSString *) urlString{
self.movieURLString = urlString;
NSURL *movieURL = [NSURL URLWithString:self.movieURLString];
self.moviePlayer = [[MPMoviePlayerController alloc] init];
[self.moviePlayer setShouldAutoplay:YES];
[self.moviePlayer setContentURL:movieURL.absoluteURL];
[self.moviePlayer setMovieSourceType:MPMovieSourceTypeFile];
self.moviePlayer.controlStyle = MPMovieControlStyleNone;
self.moviePlayer.view.frame = self.movieView.frame;
/* add tap handler */
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showControls:)];
singleFingerTap.delegate = self;
//EDIT: this line somehow didn't make into my OP
[self.moviePlayer.view addGestureRecognizer:singleFingerTap];
self.moviePlayer.view.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.moviePlayer.view];
[self.moviePlayer prepareToPlay];
// respond to changes in movie player status
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:self.moviePlayer];
}
- (void) showControls : (UITapGestureRecognizer *) recognizer {
NSLog(#"here");
self.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
}
You never added the gesture recognizer to a view, that's what's wrong.
[self.moviePlayer.view addGestureRecognizer:singleFingerTap];
There's also no need to set the delegate unless you're going to implement some of the methods in the UIGestureRecognizerDelegate protocol.

Resources