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
Related
I'm trying to implement a zoom feature for an iCarousel item view. This is my code :
NSString *pathToHDImage = [documentsFolderPath stringByAppendingPathComponent:solution.localHDURL];
if (!view) {
view = [[AsyncImageView alloc] initWithFrame:self.view.bounds];
view.contentMode = UIViewContentModeScaleAspectFit;
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinch:)];
pinchGesture.cancelsTouchesInView = false;
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
panGesture.cancelsTouchesInView = false;
pinchGesture.delegate = panGesture.delegate = self;
[view addGestureRecognizer:pinchGesture];
[view addGestureRecognizer:panGesture];
((AsyncImageView *)view).imageURL = [NSURL fileURLWithPath:pathToHDImage];
} else
((AsyncImageView *)view).imageURL = [NSURL fileURLWithPath:pathToHDImage];
The problem is that my handlePan: and handlePinch: never get called. How can I do? The main goal is to implement zoom feature for every iCarousel item view.
Try this Code:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
I did not test but I hope it helps.
In case it does not work check out this link1 and then this link2
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];
}
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.
I'm trying to add a UILongPressGestureRecognizer and a UITapGestureRecognizer to an IBOutletCollection of UIImageViews, but it's not working. Here's the code I'm using:
UILongPressGestureRecognizer *pressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(deleteImage:)];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(selectImage:)];
pressRecognizer.delegate = self;
tapRecognizer.delegate = self;
for (UIImageView *imageView in myImageViewCollection)
{
[imageView addGestureRecognizer:pressRecognizer];
[imageView addGestureRecognizer:tapRecognizer];
imageView.userInteractionEnabled = YES;
}
- (void)selectImage:(UITapGestureRecognizer *)sender
{
NSLog(#"Select");
}
- (void)deleteImage:(UILongPressGestureRecognizer *)sender
{
NSLog(#"Delete");
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
I've conformed to the UIGestureRecognizerDelegate. What am I doing wrong?
Refer to this question. Sounds like the same issue. I recreated your problem and the gesture recognizers are only bound to the last view.
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.