How to pass argument in #selector in UITapGestureRecognizer? - iphone

I have this in my table header view section:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(sectionHeaderTapped:)];
I want to pass the section number in the method sectionHeaderTapped so i can recognize which section got tapped.
My method implementation looks like this:
-(void)sectionHeaderTapped:(NSInteger)sectionValue {
NSLog(#"the section header is tapped ");
}
How can I achieve this?

The method sectionHeaderTapped should have one of the following signatures:
- (void)sectionHeaderTapped:(UITapGestureRecognizer *)sender;
- (void)sectionHeaderTapped;
You have to figure out the cell that was tapped using the coordinates of the tap.
-(void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer
{
CGPoint tapLocation = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *tapIndexPath = [self.tableView indexPathForRowAtPoint:tapLocation];
UITableViewCell* tappedCell = [self.tableView cellForRowAtIndexPath:tapIndexPath];
}
You can probably get the section header using that method. But it may be easier to attach a different gesture recognizer to each section header.
- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section
{
// ...
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(sectionHeaderTapped:)];
[headerView addGestureRecognizer:tapGesture];
return headerView;
}
And then
-(void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer
{
UIView *headerView = gestureRecognizer.view;
// ...
}

An alternate : You can add UIButton on the tableHeaderView and get click of button.

Related

How to enlarge uitableview cell image on touch

I'm using the following code to detect a touch on a table cell image. How would I go about enlarging the image on that touch?
The part I'm stuck on is how would I make the cell.userSubmittedImageView accessible from the myFunction method?
from cellForRowAtIndexPath: method
...
cell.userSubmittedImageView.userInteractionEnabled = YES;
cell.userSubmittedImageView.tag = indexPath.row;
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myFunction:)];
tapped.numberOfTapsRequired = 1;
[cell.userSubmittedImageView addGestureRecognizer:tapped];
return cell;
}
-(void)myFunction :(id) sender
{
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
NSLog(#"Tag = %d", gesture.view.tag);
}
Assuming that your userSubmittedImageView is an UIImageView you can do
UIImageView * userSubmittedImageView = (UIImageView *)gesture.view;

UITapGestureRecognizer recognized as UILongPressGestureRecognizer

I have an issue with the UITapGestureRecognizer in my collection view and I don't know the error.
I want to do a custom action when there is a long press gesture, and when there is a tap gesture I want to do nothing, so I have these methods:
- (void)activateSelectionMode:(UILongPressGestureRecognizer *)gr
{
if (![self.collectionView allowsSelection]) {
[self.collectionView setAllowsSelection:YES];
NSLog(#"Seleccion activada");
}
}
- (void)pruebaTap:(UITapGestureRecognizer *)tr
{
NSLog(#"tap");
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
CGPoint touchPoint = [touch locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:touchPoint];
if (indexPath != nil && [gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
{
CVCell *cell = (CVCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
if ([[cell checkImage] isHidden]) {
// TODO: AƱadir la celda a la lista de celdas seleccionadas
[[cell checkImage] setHidden:NO];
NSLog(#"Seleccionada celda %#", [[cell titleLabel] text]);
} else {
// TODO: Quitar la celda de la lista de celdas seleccionadas
[[cell checkImage] setHidden:YES];
NSLog(#"No seleccionada celda %#", [[cell titleLabel] text]);
}
NSLog(#"Entra");
return YES;
}
return NO;
}
IF I comment the last method, each method is recognized perfectly, but if I don't comment the last method, the tap gesture is recognized as long press gesture. Here I assign the gesture to the collection view:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(pruebaTap:)];
tap.delegate = self;
[self.collectionView addGestureRecognizer:tap];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(activateSelectionMode:)];
longPress.delegate = self;
[self.collectionView addGestureRecognizer:longPress];
Thanks so much in advance.
Not sure weather you have implemented the below gesture delegate method or not.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer
:(UIGestureRecognizer *)otherGestureRecognizer;
If you have not implemented then no problem because default implementation returns NO but if you have implemented & returned YES then both the gesture will be recognized. May be returning NO will resolve your problem
It will definitely recognize long press gesture because , you have added it last, what you are doing is , you are adding 2 gestures on same view, so here your longPress gesture will overlap on UITapGestureRecognizer gesture(that is tap), so everytime longpress gesture will be called.
what you can do is , you will have to add one at a time.

How to remove subview added in other TableView cell when tap on one cell, in Custom swipe (instead of swipe to delete) Cell (swipe to mail/sms)

In my iPhone UITable view application
I need to add Two Buttons when user swipes on table view Cell / Row.
One for Compose mail button one for Send sms button to the contacts.
I implemented following code to add Send Mail (Blue Cloud Button) only for now
//Add a left swipe gesture recognizer in view Did load
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:#selector(swipeRow:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[contactsTable addGestureRecognizer:recognizer];
[recognizer release];
- (void)swipeRow:(UISwipeGestureRecognizer *)gestureRecognizer
{
//Get location of the swipe
CGPoint location = [gestureRecognizer locationInView:contactsTable];
NSIndexPath *indexPath = [contactsTable indexPathForRowAtPoint:location];
UITableViewCell *cell = [contactsTable cellForRowAtIndexPath:indexPath];
UIButton *MailButton = [UIButton buttonWithType:UIButtonTypeCustom];
[MailButton setBackgroundImage:[UIImage imageNamed:#"sendData.png"] forState:UIControlStateNormal];
MailButton.frame=CGRectMake(150, 0, 40.0, 30.0);
[MailButton addTarget:self action:#selector(SendMail) forControlEvents:UIControlEventTouchUpInside];
//Add mail button if index path is valid
if(indexPath)
{
[cell addSubview:MailButton];
}
}
It execute fine and add button to the selected cell/row when we swipe on the cell.
But when we swipe another cell the buttons on the previous cell are does not hide / removed repeated as follows
I want to not showing (remove) buttons on the other cells while taping swipe on the other cell Only one cloud button At a time ..
Why not you can keep the button in XIb and add it to respective cell? It is a single object for the entire class, so there will be no duplicate of buttons in previous cells. Please try.
What you need is one ivar for storing the lastIndexPath where you added the cloud button.
And on every time to add new button you have to remove the button from the perviously added indexPath and assign the new indexPath to the ivar.
Your code may be look like this (not tested).
in .h file on property like
#property (strong, nonatomic) NSIndexPath *lastIndexPath;
and in .m file synthesize it.
Now the code will be look like this
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:#selector(swipeRow:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[contactsTable addGestureRecognizer:recognizer];
[recognizer release];
- (void)swipeRow:(UISwipeGestureRecognizer *)gestureRecognizer
{
//Get location of the swipe
CGPoint location = [gestureRecognizer locationInView:contactsTable];
NSIndexPath *indexPath = [contactsTable indexPathForRowAtPoint:location];
//New Code
UITableViewCell *cell = [contactsTable cellForRowAtIndexPath:indexPath];
if(lastIndexPath != nil)
UITableViewCell *last = [contactsTable cellForRowAtIndexPath:lastIndexPath];
//End
UIButton *MailButton = [UIButton buttonWithType:UIButtonTypeCustom];
[MailButton setBackgroundImage:[UIImage imageNamed:#"sendData.png"] forState:UIControlStateNormal];
MailButton.frame=CGRectMake(150, 0, 40.0, 30.0);
[MailButton addTarget:self action:#selector(SendMail) forControlEvents:UIControlEventTouchUpInside];
MailButton.tag = 1111;// New code
//Add mail button if index path is valid
if(indexPath)
{
//New Code
UIButton *mb = (UIButton *) [cell viewWithTag:1111];
[mb removeFromSuperview];
//End
[cell addSubview:MailButton];
lastIndexPath = indexPath;// New Code
}
}

how can I distinguish which part of UITableViewCell has been clicked

I have created a UITableView with a custom UITableViewCell. My cell includes one UIImageView on the left and UITextView on the right.
Inside UITableViewController, I set both image and text in tableview cellForRowAtIndexPath.
Everything shows fine but now I need to implement didSelectRowAtIndex and I need to distinguish if UIImageView or UITextView of the cell has been clicked.
Let's say, image clicking is representing delete action and the rest of the cell editing action.
Rather than adding the gesture recognisers to each individual cell, you can add one to the table view and determine which cell was selected from the point of the users touch, and then determine if the user touched the image or the cell.
First make sure your controller adopts the UIGestureRecognizerDelegate protocol.
#interface MyTableViewController() <UIGestureRecognizerDelegate>
#end
Then add the UIGestureRecognizer to the UITableView when the view loads.
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
singleTap.delegate = self;
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self.tableView addGestureRecognizer:singleTap];
}
This delegate method determines if the handleTap: method should be executed. If it can find an indexPath from the users touch, then it returns YES otherwise it returns NO.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
UITableView *tableView = (UITableView *)gestureRecognizer.view;
CGPoint p = [gestureRecognizer locationInView:gestureRecognizer.view];
if ([tableView indexPathForRowAtPoint:p]) {
return YES;
}
return NO;
}
Once we have determined if the user has clicked in a cell, the handleTap: method is called, which then decides if the user touched the image, or any other part of the cell.
- (void)handleTap:(UITapGestureRecognizer *)tap
{
if (UIGestureRecognizerStateEnded == tap.state) {
UITableView *tableView = (UITableView *)tap.view;
CGPoint p = [tap locationInView:tap.view];
NSIndexPath* indexPath = [tableView indexPathForRowAtPoint:p];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGPoint pointInCell = [tap locationInView:cell];
if (CGRectContainsPoint(cell.imageView.frame, pointInCell)) {
// user tapped image
} else {
// user tapped cell
}
}
}
You could subclass UITableViewCell and override touchesEnded.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
UIView *hitView = [self hitTest:location withEvent:event];
if (hitView == myImageView) ...;
if (hitView == myTextView) ...;
}
You need to keep some reference to your UIImageView and UITextView (they should probably be properties of your cell).
You can of course override touchesBegan instead of touchesEnded, depends on what functionality you want to achieve.
a very abstract and general answer is to do the following
For each UIImage and UILabel you add set their tag to be the indexPath.row
//When creating the label and image add a recognizer to them
label.tag = indexPath.row;
imageView.tag = indexPath.row;
Then add a UITapGestureRecognizer on each image and label, like so
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTap:)];
[label addGestureRecognizer:recognizer];
[imageView addGestureRecognizer:recognizer];
}
- (void) handleTap:(UITapGestureRecognizer*)recognizer
{
UIView *view = recognizer.view;
int row = view.tag;
if ([view isKindOfClass:[UILabel class]]) {
//Row is row
//and the label is pressed
}
if ([view isKindOfClass:[UIImageView class]]) {
//Row is row
//and the imageview is pressed
}
}
Make the image a UIButton. When the button's action is triggered, you know the user tapped the image (cell will NOT be selected). If cell is selected, you know the user tapped somewhere else on the row (including text view or label).
Also, set the button's tag property to, e.g. the cell's row index so you can know which row's image was tapped.
you have two option is to implement :-
1--add UITapGestureRecognizer in your "uitableviewcell" and make it point to image view
and pass "indexpath" as parameter to selector and make the delegate pass it to tableviewcell
UILabel *label = =[UILabel alloc]init];
label.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(labelTap)] autorelease];
[label addGestureRecognizer:tapGesture];
-(void)labelTap{
[delegate performselector#selector(labeltapped:)withobject:indexpath];
}
2- Second way is to check the sender of DidSelectRowAtIndexPath of type [imageview or label];
but i prefer the first way

click any UIImage and open an UIImageView in objective-c

I got this solution on this site: Click an UIImage and open an UIImageView in Objective-c
Add UITapGestureRecognizer to your UIImageView:
UITapGestureRecognizer *tapRecognizer;
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(yourSelector)];
[thumbnail addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
thumbnail.userInteractionEnabled = YES; // very important for UIImageView
This is working very fine for single ImageView, but I am adding more than one (about to 20) to my scrollView then How can I differentiate which ImageView will tapped or selected by user. I tried to set my own #selector(imageClicked), but it only returns tag for last imageView.
I am adding addGestureRecognizer in a loop, as I load 20 static images dynamically in an imageView.
This might help
for(int i=0;i<20;i++)
{
UIImageView *img=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"yourimage.png"]];
[img setTag:i];
img.frame= //set frame accordingly;
img.userInteractionEnabled = YES;
UITapGestureRecognizer *tap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[img addGestureRecognizer:tap];
[tap release];
[scrollView addSubView:img];
}
- (void)handleTap:(UITapGestureRecognizer *)recognizer {
UIImageView *imageView = (UIImageView *)recognizer.view;
switch([imageView tag])
{
case 1:
//do your work
break;
.
.
.
.
case n:
}
}
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
for (UIImageView *thumbnail in imageArray) {
[thumbnail addGestureRecognizer:tapRecognizer];
}
[tapRecognizer release];
You can get the view from the property "view" of UIGestureRecognizer.
In your selector, for example:
- (void)handleTap:(UITapGestureRecognizer *)recognizer {
UIImageView *imageView = (UIImageView *)recognizer.view;
// Now do something with your view
}
You cannot add a single tap recognizer to multiple views. Create a new one for every view you want to add a tap recognizer to. Since you are using a tableview just do that in the tableView:cellForRowAtIndexPath: method:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// usual implementation
static NSString *cellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeue ...];
if (!cell) {
cell = [[UITableViewCell alloc] init....];
// add new gesture recognizer here.
}
// setup cell: set the image (just an example)
cell.imageView.image = [images objectAtIndex:indexPath.row];
return cell;
}
Instead of using tags like mentioned in the other answers, and just getting the imageview try to work with the underlying model. When handling the tap, find the indexPath to know what model object to access:
- (void)handleTap:(UITapGestureRecognizer *)recognizer {
UIImageView *imageView = (UIImageView *)recognizer.view;
// assumes the image view is direct subview of the cell
// change to match your cell structure
UITableViewCell *cell = (UITableViewCell *) [imageView superview];
// get the index path for the cell clicked
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// TODO: Use index path to get full image to display
}
This way you know the exact row of the image clicked, so you can access your model to get access to the full image to display.
You need to add tag to all images - thumbnail.tag = 100 for example.Then modify your selector to youSelector:(UITapGestureRecognizer *)sender;
In selector add switch
- (void) yourSelector:(UITapGestureRecognizer *)sender {
UIImageView *imageView = (UIImageView *)sender.view;
switch(imageView.tag) {
case 100: {
//This code will be handled if tag == 100;
}
}
}
Please try to subclass the ImageView & add the gesture recognizer to the subclass.
Now for each image create the ImageView object and add the image to that object.
Set some unique property so that you can identify which object click like the name of the image.