Find and Remove Certain one UIGestureRecognizer among some same named UIGestureRecognizers - iphone

Hey, guys, I met a problem when trying to removeGestureRecognizer: from a view,
what i want to do is doubleTap one of the imageViews, and remove the tapped imageView's singleTap Gesture, without remove other imageViews singleTap Gesture.
here is how i generate views, gestures and the mechanisms:
.h
UITapGestureRecognizer *singleTap;
.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSInteger i;
for (i = 1; i <= 3; i++)
{
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(110, 70+80*(i-1), 100, 60);
imageView.backgroundColor = [UIColor whiteColor];
imageView.tag = i;
imageView.userInteractionEnabled = YES;
[self.view addSubview:imageView];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleMethod:)];
doubleTap.numberOfTapsRequired = 2;
singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleMethod:)];
[singleTap requireGestureRecognizerToFail:doubleTap];
[imageView addGestureRecognizer:doubleTap];
[imageView addGestureRecognizer:singleTap];
}
}
- (void)singleMethod: (id)sender
{
NSLog(#"SingleTap");
}
- (void)doubleMethod: (id)sender
{
NSLog(#"%d",[((UITapGestureRecognizer *)sender).view.gestureRecognizers count]);
UIImageView *imageView = nil;
NSArray *tryToFindYou = [self.view subviews];
for (imageView in tryToFindYou)
{
if ([imageView isKindOfClass:[UIImageView class]] && imageView.tag == ((UITapGestureRecognizer *)sender).view.tag)
{
[imageView removeGestureRecognizer:singleTap];
}
}
NSLog(#"%d",[((UITapGestureRecognizer *)sender).view.gestureRecognizers count]);
}
but these lines I wrote can't find exactly the singleTap Gesture attached to the double-tapped imageView.
when NSLog the .gestureRecognizers count, it still 2, what it removed is the last imageView's singleTap Gesture, it became 1, which is correct.
I can't locate the first and second one, any ideas to locate them? thank you for reading :)

You should cycle through gestureRecognizers property of the UIView class, where the gestures are added, something like this:
for (imageView in tryToFindYou)
{
if ([imageView isKindOfClass:[UIImageView class]] && imageView.tag == ((UITapGestureRecognizer *)sender).view.tag)
{
for(UIGestureRecognizer *gesture in [imageView gestureRecognizers])
{
if([gesture isKindOfClass:[UITapGestureRecognizer class]])
{
if (gesture.numberOfTapsRequired == 1)
[imageView removeGestureRecognizer:gesture];
}
}
}
}

Related

Multiple gestureRecognizers on views- one shouldn't pass touch

On parentClass(inheriting from UIView) i have:
[self addGestureRecognizer:_tapGesture]; // _tapGesture is UITapGestureRecognizer, with delegate on parentClass
On someClass:
[_myImageView addGestureRecognizer:_imageViewGestureRecognizer]; // _imageViewGestureRecognizer is UITapGestureRecognizer, with delegate on someClass
The problem is that when i tap on myImageView both gesture recognizers are firing. I want only _imageViewGestureRecognizer to work.
I've tried:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
UIView *gestureView = recognizer.view;
CGPoint point = [touch locationInView:gestureView];
UIView *touchedView = [gestureView hitTest:point withEvent:nil];
if ([touchedView isEqual:_imageViewGestureRecognizer]) {
return NO;
}
return YES;
}
But it ofc doesn't take upon consideration gesture recognizer from super class.
I did this little test and it worked perfectly...
#implementation View
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor whiteColor];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped1)];
[self addGestureRecognizer:tap];
UIImageView* img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"test.png"]];
img.userInteractionEnabled = YES;
img.frame = CGRectMake(0, 0, 100, 100);
[self addSubview:img];
UITapGestureRecognizer* tap2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped2)];
[img addGestureRecognizer:tap2];
return self;
}
-(void)tapped1 {
NSLog(#"Tapped 1");
}
-(void)tapped2 {
NSLog(#"Tapped 2");
}
#end
What you wanted was iOS's default behaviour. Once a subview has taken care of a touch, its superview won't receive the touch anymore. Did you set userInteractionEnabled on the imageView?

Getting index in NSMutableArray of selected or tapped image

I am developing an app where I add images to an NSMutableArray and display them in an image view.
My problem is that I will don't know how to get the index of the selected or tapped image in my app.
FrontsCards=[[NSMutableArray alloc]initWithObjects:#"cloub1.png",#"cloub2.png",#"cloub3.png",#"cloub4.png", nil];
for(int m=0; m< [FrontsCards count];m++)
{
NSString *imageName=[FrontsCards objectAtIndex:m];
NSString *fullImageName=[NSString stringWithFormat:#"%#",imageName];
int padding=25;
CGRect imageViewFrame=CGRectMake(scrollView.frame.size.width*m+padding, scrollView.frame.origin.y, scrollView.frame.size.width-2*padding, scrollView.frame.size.height);
ImgView=[[UIImageView alloc]initWithFrame:imageViewFrame];
[ImgView setImage:[UIImage imageNamed:fullImageName]];
[ImgView setContentMode:UIViewContentModeScaleAspectFill];
[scrollView addSubview:ImgView];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapImgView:)];
doubleTap.numberOfTapsRequired = 2;
doubleTap.delegate = self;
[self.ImgView addGestureRecognizer:doubleTap];
self.ImgView.userInteractionEnabled=YES;
}
CGSize scrollViewSize=CGSizeMake(scrollView.frame.size.width*[FrontsCards count], scrollView.frame.size.height);
[scrollView setContentSize:scrollViewSize];
[self.view addSubview:scrollView];
What should I do in my tap gesture recognizer to get the index of the image?
- (void)doubleTapImgView:(UITapGestureRecognizer *)gesture
{
NSLog(#"double-tap");
}
set a tag to each imageView you using like this :
ImgView=[[UIImageView alloc]initWithFrame:imageViewFrame];
ImgView.tag = m;
and then replace this method:
- (void)doubleTapImgView:(UITapGestureRecognizer *)gesture
{
NSLog(#"double-tap");
NSLog(#"%d", gesture.view.tag);
}
it will print you the index of the image in the imageView
maybe you can use something like this:
first add the name of the image as the accessibilityIdentifier of the the imageview
[imgView setAccessibilityIdentifier:imageName];
then in the tapRecognizer:
-(void)doubleTapImgView:(UITapGestureRecognizer *)gesture{
UIImageView *imgView = (UIImageView *)gesture.view;
int idx = [FrontCards indexOfObject:[imgView accessibilityIdentifier]];
}

Getting tag of UILabel on click

I am dynamically creating UILabels and then saving their tag in an NSMutableArray. I then have a method that detects taps (clicks) on these UILabels. Basically when a UILabel that has been dynamically generated is clicked I want to have it deleted without deleting other labels. However, in future I may want to do more then just delete. But at the moment I feel like I am stuck at a dead end trying to find a way to do this. Any ideas?
Heres my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// set corner radius
coverview.hidden=YES;
labeltextfield.hidden=YES;
textcreate.hidden=YES;
labeltags = [NSMutableArray array];
labeltext = [NSMutableArray array];
}
-(IBAction)removeboard
{
[labeltextfield resignFirstResponder];
}
-(void)showtextcreator {
// Create bg cover
coverview.hidden=NO;
labeltextfield.hidden=NO;
textcreate.hidden=NO;
//Make sure creating screen is always on top
[self.view bringSubviewToFront:coverview];
[self.view bringSubviewToFront:labeltextfield];
[self.view bringSubviewToFront:textcreate];
}
-(void)createtext {
NSInteger obj = [labeltags count] +1 ;
[labeltags addObject:[NSNumber numberWithInteger:0]];
int posx = arc4random() % 300 ;
int posy = arc4random() % 400 ;
int frame = arc4random() % 400 ;
NSString *txt = labeltextfield.text;
// NSString *framename = (#"frame%i",frame);
[labeltext addObject:txt];
[labeltags addObject:[NSNumber numberWithInteger:0]];
CGRect labelframe = CGRectMake( posx, posy, 100, 30);
label = [[UILabel alloc] initWithFrame: labelframe];
[label setText: [NSString stringWithFormat:#"%#", txt]];
[label setTextColor: [UIColor orangeColor]];
label.backgroundColor = [UIColor clearColor];
label.tag=obj;
[self.view addSubview: label];
label.userInteractionEnabled = YES;
UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:#selector(labelDragged:)];
[label addGestureRecognizer:gesture];
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction)];
[label addGestureRecognizer:recognizer];
coverview.hidden=YES;
labeltextfield.hidden=YES;
textcreate.hidden=YES;
}
- (void)labelDragged:(UIPanGestureRecognizer *)gesture
{
label = (UILabel *)gesture.view;
CGPoint translation = [gesture translationInView:label];
// move label
label.center = CGPointMake(label.center.x + translation.x,
label.center.y + translation.y);
// reset translation
[gesture setTranslation:CGPointZero inView:label];
}
- (void)tapAction {
UILabel *labelnew = (UILabel *)[self.view viewWithTag:1];
NSLog(#"Text is %#",labelnew.text);
}
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapAction:)];
[label addGestureRecognizer:recognizer];
- (void)tapAction:(UITapGestureRecognizer *)tapGesture {
UILabel *labelTapped = (UILabel *)tapGesture.view;
//delete it using removeFromSuperView or do whatever you need with tapped label
}
Details:
1.Modify your -(void)createtext method.
2: Add a parameter to the target for UITapGestureRecognizer
3.Receive the sender gesture in - (void)tapAction:
4.Get the tapped UILabel.
Thats it.

detect a touch down event on UIImageView(s)

I placed 4 UIImageView on UIView and I named them
UIImageView myImg1 = [[UIImageView alloc] init];
UIImageView myImg2 = [[UIImageView alloc] init];
UIImageView myImg3 = [[UIImageView alloc] init];
UIImageView myImg4 = [[UIImageView alloc] init];
How can I tell the compiler that I have just touched down UIImageView 1 or UIImaveView 2. If I only can use UIImageView to do this task, not buttons at all. Please guide me about this issue. Thanks
A stylish solution is to use the UIGestureRecognizer object:
in your loadView method (or anywhere you code the UIImageView(s) drawing...):
UITapGestureRecognizer *tapRecognizer;
UIImageView *anImageView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
[anImageView setTag:0]; //Pay attention here!, Tag is used to distinguish between your UIImageView on the selector
[anImageView setBackgroundColor:[UIColor redColor]];
[anImageView setUserInteractionEnabled:TRUE];
tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewDidTapped:)] autorelease];
tapRecognizer.numberOfTapsRequired = 1;
[anImageView addGestureRecognizer:tapRecognizer];
[contentView addSubview:anImageView];
[anImageView release];
UIImageView *anotherImageView = [[UIImageView alloc] initWithFrame:CGRectMake(80, 180, 100, 100)];
[anotherImageView setTag:1]; //Pay attention here!, Tag is used to distinguish between your UIImageView on the selector
[anotherImageView setBackgroundColor:[UIColor greenColor]];
[anotherImageView setUserInteractionEnabled:TRUE];
tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewDidTapped:)] autorelease];
tapRecognizer.numberOfTapsRequired = 1;
[anotherImageView addGestureRecognizer:tapRecognizer];
[contentView addSubview:anotherImageView];
[anotherImageView release];
This is a simple imageViewDidTapped: sample method that you can use to distinguish between the two sample UIImageView objects above:
- (void)imageViewDidTapped:(UIGestureRecognizer *)aGesture {
UITapGestureRecognizer *tapGesture = (UITapGestureRecognizer *)aGesture;
UIImageView *tappedImageView = (UIImageView *)[tapGesture view];
switch (tappedImageView.tag) {
case 0:
NSLog(#"UIImageView 1 was tapped");
break;
case 1:
NSLog(#"UIImageView 2 was tapped");
break;
default:
break;
}
}
You should consider using the tag property for this. Give each image a unique tag, then use this information to determine which image was touched. For example, set the tags by
UIImageView myImg1 = [[UIImageView alloc] init];
myImg1.tag = 1;
and when you receive a touch for img, call
img.tag
to retrieve the tag.
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
singleFingerTap.numberOfTapsRequired = 1;
[myImg1 addGestureRecognizer:singleFingerTap];
[myImg2 addGestureRecognizer:singleFingerTap];
[singleFingerTap release];
And action method
-(void)handleSingleTap:(UIGestureRecognizer*)sender{
//your code here
}
You can do like this.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if(CGRectContainsPoint(myImg1.view.frame,touchLocation))
{
NSLog(#" Image 1");
}
else if(CGRectCont..
Note..the NSLog will be outputted if the point lies in more than one image view..
in that case..check which image view is on top..

Do something to selected image in scroll view

I try to make following: Horizontal list of images, that I can select and do something with it. For example flip image around x axis. I know how to rotate image. I created scrollview and load it with images. I added event handler when I tap on image. But I don't know how to do something with tapped image. How to code method to do something with tapped image?
- (void)viewDidLoad {
[super viewDidLoad];
img1 = [UIImage imageNamed:#"imgTest.jpg"];
img2 = [UIImage imageNamed:#"imgTest2.jpg"];
arrayOfImages = [[NSMutableArray alloc] init];
[arrayOfImages addObject:img1];
[arrayOfImages addObject:img2];
[arrayOfImages addObject:img1];
[arrayOfImages addObject:img2];
scrollView = [[UIScrollView alloc] init];
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
scrollView.directionalLockEnabled = YES;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.delegate = self;
scrollView.backgroundColor = [UIColor blueColor];
scrollView.autoresizesSubviews = YES;
scrollView.frame = CGRectMake(0, 0, 320, 128);
[self.view addSubview:scrollView];
UIImage *imageToAdd;
int x = 0;
int y = 0;
for(imageToAdd in arrayOfImages)
{
UIImageView *temp = [[UIImageView alloc] initWithImage:imageToAdd];
temp.frame = CGRectMake(x, y, 128, 128);
temp.userInteractionEnabled = YES;
x += 135;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapped:)];
[temp addGestureRecognizer:tap];
[scrollView addSubview:temp];
}
...
- (void)imageTapped:(UIGestureRecognizer *)sender
{
// how to get reference on selected item in scrollview???
}
A gesture recognizer has a view property that returns the view associated with the recognizer. Since you know that it'll be a UIImageView you can simply cast it and use it as in:
UIImageView *iv = (UIImageView *)[sender view];
And your image can then be queried via:
UIImage *image = [iv image];
If you need to know the index in your array, there are two ways: either simply use [arrayOfImages indexOfObject:image];, or you can assign tags (numbers) to views and use them. A tag is not used by Apple, it's only here so we developers can "mark" views in some way. For example:
NSInteger counter = 0;
for(imageToAdd in arrayOfImages)
{
UIImageView *temp = [[UIImageView alloc] initWithImage:imageToAdd];
count.tag = counter++;
...
}
Then, in your imageTapped:, you can query the index via tag:
NSInteger index = [imageView tag];