I have a large button that swiping up and down on it fires some methods using simple gestures.
A single tap on it fires up TouchUpInside event with largestButtonSingleTap.
My problem is if I tap the largeButton and keep it pressed, then after a second swiping up the swiping gesture won't work. Trying to figure out why.
I have a few other events on that button such as DragInside , TouchDown , DragExit , TouchCancel. I cancelled all of them and stayed with an empty method (commented out everything inside largestButtonSingleTap) but still, if the button is pressed > small pause > swipeUp > won't fire.
Thanks
UISwipeGestureRecognizer *upRecognizer;
upRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeUp:)];
[upRecognizer setDirection: UISwipeGestureRecognizerDirectionUp];
[_largestButton addGestureRecognizer:upRecognizer];
- (IBAction)largestButtonSingleTap:(UIButton *)sender
{ //some more code here
[UIView animateWithDuration:0.4 animations:^() {
...
}completion:^(BOOL finished){}];
...
}
-
EDIT:
After reading the answers suggested here I've started a new project thinking that there's something wrong with my code but it still doesn't work. Here is the new project http://pastebin.com/yz7NaqUD
UISwipeGestureRecognizer is Discrete Gestures, so you can not do that.
https://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/GestureRecognizer_basics/GestureRecognizer_basics.html
Touchdown can go with other Continuous Gesture like Pan, pinch, rotation.
Try another way,subclass UIButton and implement touchesMove.
Refer:iOS Custom gesture recognizer measure length of longpress
the animation block may be blocking user interaction. Try using the allowUserInteraction animation option in your largestButtonSingleTap: method.
[UIView animateWithDuration:0.4 delay:0.0f options:UIViewAnimationOptionAllowUserInteraction animations:^{
//
} completion:^(BOOL finished) {
//
}];
Try setting the delegate to your gesture recognizer and implementing:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return YES;
}
Related
I am having difficulty getting a UITapGestureRecognizer to detect every tap that is occurring. For context, I am making a drumming app. I have gotten the tap gesture recognizer to work correctly, but the user should be able to tap very quickly to drum, and the recognizer is only picking up on let's say a tap every so often (if you try to tap as quickly as you can).
I am guessing this has to do with iOS categorizing very quick taps in a row as one gesture, but is there any way to get every time a finger goes down as a tap event?
I have tried using UILongPressGestureRecognizer with a small press duration.
I have tried setting the requiredNumberofTouches and requiredNumberofTaps to 1.
The code does not seem necessary to post in order to answer the question, but I will post it if you request it.
Any help would be most appreciated!
EDIT: I am adding my code, since it may help:
-(void)tap:(UITapGestureRecognizer *)tapGestureRecognizer {
CGPoint location = [tapGestureRecognizer locationInView:[self view]];
switch ([self validateTouchLocation:location]) {
case 0:
return;
case 1:
[[ASSoundManager sharedManager] playSoundNamed:#"SD0025" ofType:#"mp3"];
break;
case 2:
default:
[[ASSoundManager sharedManager] playSoundNamed:#"SD0010" ofType:#"mp3"];
break;
}
float tapWidth = 30;
ASDrumTapView *drumTapView = [[ASDrumTapView alloc] initWithFrame:CGRectMake(location.x - (tapWidth / 2), location.y - (tapWidth / 2), tapWidth, tapWidth)];
[drumTapView setBackgroundColor:[UIColor clearColor]];
[drumTapView setNeedsDisplay];
[[self view] addSubview:drumTapView];
float animDuration = 0.75;
CGRect frame = [drumTapView frame];
[UIView animateKeyframesWithDuration:animDuration
delay:0.0
options:0
animations:^{
[UIView addKeyframeWithRelativeStartTime:0
relativeDuration:animDuration
animations:^{
[drumTapView setFrame:CGRectInset(frame, -frame.size.width, -frame.size.height)];
}];
[UIView addKeyframeWithRelativeStartTime:0
relativeDuration:3*animDuration/5
animations:^{
[[drumTapView layer] setOpacity:0.0];
}];
}
completion:^(BOOL finished) {
[drumTapView removeFromSuperview];
}];
}
There could be many reason:
One possible reason could be fact that your audio engine cannot play next sound before previous sound has finished.
Check multipleTouchEnabled property on UIView
If your view is embedded in UIScrollView or any derived class, check delaysContentTouches property
While I appreciate everyone's input, I figured it out on my own.
In my code, I am running a keyframe animation with options set to 0. What this means is that during the animation, user interaction with the view is not enabled.
By setting options to UIKeyframeAnimationOptionAllowUserInteraction, I am able to pick up on taps even though one of the subviews is still in animation.
Hope this helps someone else!
I found some questions and answers here on stackoverflow for that problem, but none of the solutions there solved my problem.
My iOS App has the ability to play some music with a nice music player. I designed it with Xcode's Interface Builder and dragged out a UIView and changed its class to MPVolumeView. Everything works fine when I'm debugging my app on my iPhone 6.
Here is my problem: I also dragged out a UITapGestureRecognizer on my whole view which contains my controls like
play/pause, next/previous track (...)
and also my MPVolumeView. When I tap on that view it should fade out and disappear. Then I added a UITapGestureRecognizer on my UIImageView which shows my artwork image of the song. When I tap this image view, it should fade in my view with all controls in int - that's working properly.
BUT: When I slide the knob of the volume slider just a little bit, or if I am just touching it, the view still disappears. It seems like my MPVolumeView is forwarding my touch or something like that. I tried setting userInteractionEnabled = false on my volume slider, but that didn't help. I also set the delegate of my gesture recognizer to self and added the
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
NSLog(#"tapped");
if([gestureRecognizer.view isMemberOfClass:[UIImageView class]]) {
return true;
}
return false;
}
function to my code, which returns true or false, depending on which view I'm tapping. When I'm accessing the gestureRecognizer.view property, it doesn't recognize my MPVolumeView, just the UIView in the background.
Here my two methods which are fired after when the TapGestureRecognizers are fired:
- (IBAction)overlayViewTapped:(UITapGestureRecognizer *)sender {
if(sender.state == UIGestureRecognizerStateEnded) {
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{ self.blackOverlayView.alpha = 0.0; self.normalTimeLabel.alpha = 1.0; }
completion:nil];
}
}
- (IBAction)imageViewTapped:(UITapGestureRecognizer *)sender {
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{ self.blackOverlayView.alpha = 1.0; self.normalTimeLabel.alpha = 0.0; }
completion:nil];
}
Please help me, I'm nearly going nuts with that ..
EDIT: My music player looks like this:
After I tap anywhere on the view (except the subviews), the view should fade out and hide everything, just show the artwork image of the song and the current elapsed time. This will look like this:
As I said - the problem is, if I just tap the volume slider or slide it just a little bit, my UITapGestureRecognizer fires and fades out my complete view. How can I prevent that?
It is behaving the way it is simply because you added the gesture recognizer to the entire UIView, which includes the volume slider and whatnot.
Instead of detecting the touch in the entire view, check to see if the touch is in the area you want it.
Create a CGRect property, I'll call it touchArea:
#property CGRect touchArea;
Then specify the size of the touchArea (you can do this in the viewDidLoad):
touchArea = CGRectMake(0.0, 240.0, 320.0, 240.0);
You will have to find out where you want this and how big it should be and replace my example values with the real ones. A simple way of cheating this is to take something like a UILabel in IB and positioning and sizing it to your desire, then go to the size inspector pane and get the x, y, width and height values.
Then, before you do your fade animation, check to see if the touch was in the touchArea:
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint touchPoint = [gestureRecognizer locationInView:self.view];
if (CGRectContainsPoint(touchArea, touchPoint))
{
//do your animation here.
}
}
As a note, I would set a BOOL to check whether or not the view is faded in or out, so you can always check before animating.
I have a UIView called sineWave that renders an animated sine wave. I add sineWave as a subview by doing [self.view addSubview:self.sineWave];. I have another UIView called panedView which is the highest/top view/layer. As panedView is dragged up, sineWave view is revealed. I add panedView above sineWave view by doing [self.view insertSubview:panedView aboveSubview:self.sineWave];. When I pan up everything works perfectly. However, since adding the sineWave view I have an issue swiping up. When I swipe up, I can see that the swipe method gets called, but my view doesn't move up where it should. However, if I swipe a second time immediately after my first swipe, my view will move to where its programmed to - revealing the sine wave. Any idea why this would occur?
- (IBAction)handleUpSwipe:(UISwipeGestureRecognizer *)recognizer
{
NSLog(#"Swipe UP");
[UIView animateWithDuration:.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
panedView.frame = CGRectOffset(panedView.frame, 0, -1*self.view.bounds.size.height*.80);
} completion:nil];
[self displaySine];
}
-(void) displaySine
{
if(sineIsDisplaying == NO)
{
self.sineWave = [[OSDrawWave alloc] initWithFrame:CGRectMake(-1*self.view.bounds.size.width, (.75*self.view.bounds.size.height), 2*self.view.bounds.size.width, .3125*(2*self.view.bounds.size.width))];
[self.sineWave setBackgroundColor:[UIColor clearColor]];
[self.sineWave animateWave];
[self.view addSubview:self.sineWave];
[self.view insertSubview:panedView aboveSubview:self.sineWave];
sineIsDisplaying = YES;
}
}
kindly tell me which gesture they are using in my given screen shoot. If there is any example code or similar to this example then please tell me. I search over google with more than 15 different queries but did find any example like this .
As you can see they are not using a full page swipe but half.
Please check these two screen shoots
Thanks
You can use simple view animation for the same.
-(IBAction)tabPressed:(id)sender
{
if([sender isSelected])
{
sender.selected=NO;
[UIView beginAnimations:#"animation" context:NULL];
[UIView setAnimationDuration:0.5];
//set here frame to go down
[UIView commitAnimations];
}
else
{
sender.selected=YES;
[UIView beginAnimations:#"animation" context:NULL];
[UIView setAnimationDuration:0.5];
//set here frame to go up
[UIView commitAnimations];
}
}
Seems like there's a low-level work with gestures based on touchesBegan: and touchesMoved: methods.
Just Create A UITapGesture like this
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
And Do Something here For Hide According You ...
- (void) handleTapFrom: (UITapGestureRecognizer *)recognizer
{
//Code to handle the gesture
}
Could be everything:
a simple button that trigger a slide up animation
if you can drag it and it stays attached to the finger is a pan Gesture recognizer
if the movement is a swipe, it is a swipe gesture recognizer
I have a button which I would like to show and hide as the iOS MPMoviePlayer controls do when the video is tapped. Is there an better way to do this other than making my own gesture recognizer and timer for hiding/showing the button when the apple ones do?
That would be your best option. Here's roughly what it could look like:
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(videoTapped:)];
[videoView addGestureRecognizer:recognizer];
...
- (void)videoTapped:(UITapGestureRecognizer *)recognizer {
[UIView animateWithDuration:0.25f animations:^{
buttonView.alpha = (CGFloat)!buttonView.alpha;
}];
}
Let me know if you have any other questions.