Is it possible to alloc only one UIPanGestureRecognizer and attach to multiple views? I have multiple on-screen UIImageView objects that user can move (pan). If I'm making alloc and attaching the same UIPanGestureRecognizer object to all views then the pan gesture works only on the last attached view. I did a workaround by making multiple alloc/init of UIPanGestureRecognizer, I mean one different UIPanGestureRecognizer object for each view. Here's the code:
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer * pgr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(updateImagePosition:)];
[self.panningBtn1 addGestureRecognizer:pgr];
[pgr release];
pgr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(updateImagePosition:)];
[self.panningBtn2 addGestureRecognizer:pgr];
[pgr release];
...
PS. I also have enabled MultipleTouchEnabled & UserInteractionEnabled. Are there any more elegant solutions?
No - each UIGestureRecognizer can only belong to one view. Just create multiple with the same properties and assign them to the different views.
I suggest creating the gesture recognizer in a method:
-(UIGestureRecognizer *)myGRMethod {
UIPanGestureRecognizer *pgr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(updateImagePosition:)];
return [pgr autorelease];
}
and then just doing
for (UIView *view in views) {
[view addGestureRecognizer:[self myGRMethod]];
}
Related
In viewDidLoad I set:
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[swipeGesture setDirection:(UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight)];
[self.view addGestureRecognizer:swipeGesture];
-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
NSLog(#"Swipe received.");
UISwipeGestureRecognizerDirection temp = recognizer.direction;
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft)
{
[self backCalendarPressed:nil];
}
else if (recognizer.direction == UISwipeGestureRecognizerDirectionRight)
{
[self nextCalendarPressed:nil];
}
}
but recognizer.direction is always equal to '3'.
And that's why I can't determine if it's left or right swipe.
you have to set a separate gesture recognizer for each direction if you want to discern between left and right gestures. the direction property only gives you what you set as allowed direction (3 = both directions).
You can give the same target method to both, and in that method ask for the direction of the recognizer as you are doing.
You should try this. It is working fine.
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(backCalendarPressed:)];
[swipeLeft setDirection: UISwipeGestureRecognizerDirectionLeft ];
[self.view addGestureRecognizer:swipeLeft];
swipeLeft=nil;
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(nextCalendarPressed:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[self.view addGestureRecognizer:swipeRight];
Basically you cannot set multiple directions to a single Swipe gesture recognizer. Use separate gesture recognizers for Left and Right directions.
try this:
The direction property only defines the allowed directions that are recognized as swipes, not the actual direction of a particular swipe.
The easiest would be to use two separate gesture recognizers instead.
If you want to capture swipes left and right that you can differentiate between, you'll have to set up a separate recognizer for each. Apple does this in their Simple Gesture Recognizers
UISwipeGestureRecognizer *swipeGestureLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFromLeft:)];
[swipeGestureLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[self.view addGestureRecognizer:swipeGestureLeft];
UISwipeGestureRecognizer *swipeGestureRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFromRight:)];
[swipeGestureRight setDirection:UISwipeGestureRecognizerDirectionRight];
[self.view addGestureRecognizer:swipeGestureRight];
-(void)handleSwipeFromLeft:(UISwipeGestureRecognizer *)recognizer {
[self backCalendarPressed:nil];
}
-(void)handleSwipeFromRight:(UISwipeGestureRecognizer *)recognizer {
[self nextCalendarPressed:nil];
}
You should implement all the UIGestureRecognizer states in this handler method. Thus you can handle all the cases. I am stating this because I suspect the gesture recognizer has not yet properly recognized it's gesture. Try looking for the direction in the UIGestureRecognizerStateChanged case.
I am using :
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleViewClicked:)];
[tmp addGestureRecognizer:gestureRecognizer];
[gestureRecognizer release];
to get notification when a view(bigview for our example) i clicked(I have a lot of view), and in the front there is a UIView (a blank one) the he is in the front of the view (there is a reason why this view is in the front before al the views).
there is now a problem to get notification when tmp is tapped because the bigview is in the front.
there is any solution for something like this?
EDIT
In the bigview i have UISwipeGestureRecognizer:
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeRight:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[itemsView addGestureRecognizer:recognizer];
[recognizer release];
and if i make userInteractionEnabled in the bigview to NO he don't get notification on swipe
Two options:
A. Set userInteractionEnabled to NO on that big/blank view.
B. Implement pointInside:withEvent: on that big/blank view
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
// UIView will be "transparent" for touch events if we return NO
return NO;
}
(as taken from allowing-interaction-with-a-uiview-under-another-uiview)
I added this code in cellForRowAtIndexPath
UISwipeGestureRecognizer *gestureR = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSwipeFrom:)];
[gestureR setDirection:UISwipeGestureRecognizerDirectionRight];//|UISwipeGestureRecognizerDirectionRight)];
[cell addGestureRecognizer:gestureR];
it works fine. But I want UISwipeGestureRecognizerDirectionLeft so Added like this
[gestureR setDirection:UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight)];
When I check with direction and state I am always getting 3 = 3
- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
NSLog(#"%d = %d",recognizer.direction,recognizer.state);
}
if I apply only one Gesture it works fine. I tried to add two gestures one by one. but it will responding for only one gesture.
How to add second gestures. I added directly to one gesture to TableView another one to cell but now use.
Try this
UISwipeGestureRecognizer* gestureR;
gestureR = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom)] autorelease];
gestureR.direction = UISwipeGestureRecognizerDirectionLeft;
[view addGestureRecognizer:gestureR];
gestureR = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom)] autorelease];
gestureR.direction = UISwipeGestureRecognizerDirectionRight; // default
[view addGestureRecognizer:gestureR];
If you want to handle different functionalities on left and right swipes, just change the selectors.
Instead of two times alloc, it would be better if you use
UISwipeGestureRecognizer* recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
[recognizer setDirection:UISwipeGestureRecognizerDirectionLeft+UISwipeGestureRecognizerDirectionRight];
[cell addGestureRecognizer:recognizer];
And get the direction of swipe in the action as :
-(void)handleSwipe:(UISwipeGestureRecognizer *) sender
{
if (sender.direction == UISwipeGestureRecognizerDirectionLeft)
{
//do something
}
else //if (sender.direction == UISwipeGestureRecognizerDirectionRight)
{
//do something
}
}
I know its been ages since you asked this.
But try and read following line again in your question.
[gestureR setDirection:UISwipeGestureRecognizerDirectionRight|UISwipeGestureRecognizerDirectionRight)];
Did you realise you added UISwipeGestureRecognizerDirectionRight. Twice!!
:D
In the UIView, there is several sub views of UIImageView objects.
Since I need to detect the touch events from the UIImageView and from the remaining area of the UIView.
Can I implement touch events in UIView and UIImagView simultaneously ?
Thanks.
Based on your comment, I think you should consider gesture recognizers. Use the UITapGestureRecognizer to identify and respond to taps on a view.
UITapGestureRecognizer *tapGesture;
tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapOnView:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[view addGesture:tapGesture];
[tapGesture release];
...
tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapOnImage:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[imageView addGesture:tapGesture];
[tapGesture release];
...
define -(void)handleTapOnView:(UITapGestureRecognizer*)gesture and -(void)handleTapOnImage:(UITapGestureRecognizer*)gestureand handle the touches there.
There are other kinds of gestures too. You can read more about them here.
I am initializing my gesture recognizers with the following code when I initialize a view. However, after multiple times of presenting a view on top of the one with the gesture recognizers and dismissing it with presentModalViewController and dismissModelViewController, the gesture recognizers stop working on the original view. I've tried manually releasing the recognizers in the view's dealloc function rather than using autorelease, but it doesn't seem to help. Does anyone have any ideas? Thanks!
Also, I should mention that this problem only happens on the device, and not the simulator.
-(void) initializeGestures {
recognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)] autorelease];
//recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
[(UITapGestureRecognizer *)recognizer setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:recognizer];
recognizer.delegate = self;
swipeLeftGesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGestureLeft:)] autorelease];
//swipeLeftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGestureLeft:)];
swipeLeftGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeftGesture];
swipeLeftGesture.delegate = self;
swipeRightGesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGestureRight:)] autorelease];
//swipeRightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeGestureRight:)];
swipeRightGesture.direction = UISwipeGestureRecognizerDirectionRight; // default
[self.view addGestureRecognizer:swipeRightGesture];
swipeRightGesture.delegate = self;
}
-(IBAction) handleSwipeGestureLeft:(UISwipeGestureRecognizer*)sender
{
[self swipeLeft];
}
-(IBAction) handleSwipeGestureRight:(UISwipeGestureRecognizer*)sender
{
[self swipeRight];
}
-(IBAction) handleTapGesture:(UITapGestureRecognizer *) sender {
[self gotoDefinition];
}
did the view with gesture recognizers dealloc when you present another viewController?
this will cause the view remove gesture recognizers on it