I set my GestureRecognizer like this
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[self addGestureRecognizer:singleFingerTap];
singleFingerTap.numberOfTapsRequired = 3;
and the selector:
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
NSLog(#"yyeyyyyeyyyyyeyyyyye");
}
The class is a subclass of UIView and I want the selector to be fired on the third time - but it only works when setting numberOfTapsRequired to 1.
I wondered why the gestureRecognizer never recognized anything so I changed and swapped so many things until I realized it's working perfectly fine except that it won't do anything when the numberOfTapsRequired is anything but 1.
Any ideas about this?
EDIT: It somehow does work on iPads with iOS 7 and iOS 8. I would have guessed there is something with the constraints limiting the touch area but the 1 click does work on all devices so what else can be the difference here?
Related
I have a custom scroll view that works well before iOS 13 that uses UIPanGestureRecognizer:
_panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
_panRecognizer.delegate = self;
- (void)handlePan:(UIGestureRecognizer *)gestureRecognizer
{
UIPanGestureRecognizer* pgr = (UIPanGestureRecognizer*)gestureRecognizer;
if (pgr.state == UIGestureRecognizerStateChanged) {
// do something
}
}
Now it didn't work well with iOS 13. The handlePan function does not get called anymore until 3 fingers are panning together. In iOS 12, this function will be called when just 1 finger is moved.
I have tried setting the min/maximumNumberOfTouches but not working. Is there anything changed?
It sounds like your gesture is now competing with a system gesture. Did you check the .gestureRecognizers property of the view to see if something changed?
You might have to implement gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) delegate method, by default it returns false.
So I was just trying to make a replica of flappy bird. But, I was wondering how to achieve a bird flap? I thought of using the method
- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event
but I noticed that if you use this method and press down on the screen, the bird will flap continuously. I just want the bird to flap when I tap the screen, and if I press down on the screen it will behave the same way as tapping once.
Is there a class reference that utilizes these sort of action?
For getting the tap event, you can use the UITapGestureRecognizer provided by Apple.
Simply initiate it, set the parameters according to your requirements and add it to the view you want to record the tap.
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[demoView addGestureRecognizer:tap]; // The gesture recognizer is being added to demoView
[tap release]; // In case of not using ARC
And the define the selector which you mentioned in the initialization.
- (void)handleTap:(UITapGestureRecognizer *)recognizer{
// Handle the tapping here
}
I´m very frustrated because I can´t draw the Ground like in Flappy Bird... I try to use this method:
private void drawGround(){
for(Rectangle mRectangleGroundHelper : mArrayGround){
if(spawnGround & mRectangleGroundHelper.x<0){ // spawn Ground if the actual ground.x + ground.width() is smaller then the display width.
mArrayGround.add(mRectangleGroundHelper);
spawnGround = false;
}
}
for(Rectangle mRectangleGroundHelper : mArrayGround){
if(mRectangleGroundHelper.x < -mTextureGround.getWidth()){ // set boolean to true, if the actual ground.x completely hide from display, so a new ground can be spawn
spawnGround = true;
}
}
for(Rectangle mRectangleGroundHelper : mArrayGround){ // move the ground in negative x position and draw him...
mRectangleGroundHelper.x-=2;
mStage.getSpriteBatch().draw(mTextureGround, mRectangleGroundHelper.x, mRectangleGroundHelper.y);
}
}
You can download app at here
It seems you cannot rotate the map view using user's two finger gesture anymore. It has been a while since I did any iOS development but pre-ios6 it was automatically enabled.
Is this the case or is it me being ridiculous? It seems to me that its a very basic requirement for developers to be able to allow their users to rotate the map.
Any links to documentation that specifically says we can't rotate or some clarification would be much appreciated.
Try UIRotationGestureRecognizer to rotate map.Following code will help you.
UIRotationGestureRecognizer *rgrr = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotateMap:)];
[mapView addGestureRecognizer:rgrr];//mapView -->your mapview
rgrr.delegate = self;
////////
- (void) rotateMap:(UIRotationGestureRecognizer *)gestureRecognizer{
gestureRecognizer.view.transform = CGAffineTransformRotate(gestureRecognizer.view.transform, gestureRecognizer.rotation);
gestureRecognizer.rotation = 0; }
I have an iPad app (XCode 4.6, Storyboards, iOS 6.2). I have a scene made up like this:
UIView (subViewData - covers the right quadrant of #2, below and to the right not covering the times and names of #2- contains appointment info (cust name, and the duration is shaded)
UIView (subViewGrid - covers bottom half (in image, it contains times on the left margin and names across the top margin.)
UIScrollView (covers the bottom half view)
UIView ------- UIView (one on the top half of the window, the other on the bottom half)
UIViewController (named CalendarViewController)
This is the code to initialize the UITapGestureRecognizer found in -viewDidLoad of the CalendarViewController:
// setup for tap recognizer
UITapGestureRecognizer *fingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(singleFingerTap:)];
fingerTap.numberOfTapsRequired = 1;
fingerTap.numberOfTouchesRequired = 1;
[subViewData addGestureRecognizer:fingerTap];
This is the code in subViewData (#1) that is NOT getting executed:
- (void)singleFingerTap:(UITapGestureRecognizer*)gesture {
CGPoint pt = [gesture locationInView:self];
UIView *v = [self hitTest:pt withEvent:nil];
if(v.tag == 100) // if this is for calendar, return
return;
CGRect dataRect = CGRectMake(110.0,48.0,670.0,1450);
CGPoint dataPoint = CGPointMake(pt.x, pt.y);
// check to see if point is within the rectangle
if(!CGRectContainsPoint(dataRect, dataPoint)) {
NSLog(#"\n\nNOT within subViewData");
return;
}
else {
NSLog(#"\n\nIS within subViewData");
}
}
The question is why is it not capturing the taps? Is the recognizer code supposed to be in the controller or the view that is supposedly getting the taps? I have read almost everything I can find on the subject, but can't find anything within this specific scenario. Help is greatly appreciated.
You say:
This is the code to initialize the UITapGestureRecognizer found in -viewDidLoad of the CalendarViewController
And that code says:
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(singleFingerTap:)];
Then you must put singleFingerTap: in CalendarViewController, because you have told the gesture recognizer that the target is self, and self is an instance of CalendarViewController.
You also say:
This is the code in subViewData (#1) that is NOT getting executed
But I do not know what "in subViewData" means; you did not mention anything called "subViewData" in your explanation of the interface. Anyway it doesn't matter. You've specified self so the code needs to be in self.
However, it sounds to me as if the view in question is never receiving the touch at all. Perhaps it is not exposed (i.e. it's covered by another view). Perhaps its userInteractionEnabled is NO. There could be lots of reasons.
In my app I have added the new Gesture Recognizers that are available in the 3.2 SDK. Everything appears to be working correctly and the response time on the screen been very fast. But for some reason when I add requireGestureRecognizerToFail to some of my gestures, there is a very visible delay when the gesture is triggered. Below is a snippet of the code that I use to create the Gesture Recognizers. Does anyone know why there is a delay and how I can fix it? I'm using requireGestureRecognizerToFail to prevent the SingleTap gesture from triggering when the user performs a DoubleTap.
- (void)createGestureRecognizers {
//Single Finger Double-Tap
UITapGestureRecognizer *singleFingerDTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleDoubleTap:)];
singleFingerDTap.numberOfTapsRequired = 2;
[super addGestureRecognizer:singleFingerDTap];
//Single Finger Tap
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleTap:)];
singleFingerTap.numberOfTapsRequired = 1;
[singleFingerTap requireGestureRecognizerToFail:singleFingerDTap];
[self addGestureRecognizer:singleFingerTap];
//Two Finger Pan
UIPanGestureRecognizer *panGesture2 = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePanGesture2:)];
panGesture2.maximumNumberOfTouches = 2;
[super addGestureRecognizer:panGesture2];
//Single Finger Pan
UIPanGestureRecognizer *panGesture1 = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePanGesture1:)];
panGesture1.maximumNumberOfTouches = 1;
[panGesture1 requireGestureRecognizerToFail:panGesture2];
[super addGestureRecognizer:panGesture1];
[singleFingerDTap release];
[singleFingerTap release];
[panGesture1 release];
[panGesture2 release];
}
If you want to distinguish between a single and double tap, you must wait long enough to figure out that no second tap is coming before you can call it a single tap. The alternative would be to design all your single tap actions in such a way that they can asynchronously be canceled or reverted when a double tap is detected.
For example, if you have a single tap change pages and a double tap zoom, then you would have to animate a page changing on single tap, then reverse the animation and zoom instead when a second tap is detected. By then the view that handled the single tap may have moved. In most cases, that is more trouble and confusion then it is worth.