How to detect tap only on cells not on whole collection view? - ios

I have collectionView in my app. I have a requirement that I should be able to both double & single tap on cells to perform diffrent operations. To make it possible both double & single tap gesture on the collectionView I have added both the gesture on collection view & got the location by below code.
-(void)handleSingleTap:(UITapGestureRecognizer *)gestureRecognizer
{
if([arr_userAlbums count]>0)
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
{
return;
}
p = [gestureRecognizer locationInView:self.collection_view];
NSIndexPath *indexPath = [self.collection_view indexPathForItemAtPoint:p];
celltTapped_index_path=indexPath;
}
}
-(void)handleDoubleTap:(UITapGestureRecognizer *)gestureRecognizer
{
if([arr_userAlbums count]>0)
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
{
return;
}
p = [gestureRecognizer locationInView:self.collection_view];
NSIndexPath *indexPath = [self.collection_view indexPathForItemAtPoint:p];
celltTapped_index_path=indexPath;
}
}
But in this case the whole screen even where cells are not visible it is accepting the double tap & single tap. I want to detect single & double tap only on cells not the whole collection view.

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cvCell";
customCell *cell = (customCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.img_Collection.image = [imgArray objectAtIndex:indexPath.row];
cell.lbl_Collection.text = [lblArray objectAtIndex:indexPath.row];
cell.tag = indexPath.row;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
singleTap.numberOfTapsRequired = 1;
singleTap.delaysTouchesEnded = YES;
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
doubleTap.numberOfTapsRequired = 2;
[singleTap requireGestureRecognizerToFail:doubleTap];
[cell addGestureRecognizer:singleTap];
[cell addGestureRecognizer:doubleTap];
return cell;
}
-(void)handleSingleTap:(UIGestureRecognizer *)recognizer
{
NSLog(#"The single tap happened for %ld th index",recognizer.view.tag);
}
-(void)handleDoubleTap:(UIGestureRecognizer *)recognizer
{
NSLog(#"The Double tap happened for %ld th index",recognizer.view.tag);
}

you can get tapped View by using hitTest Method like this
UIView *tappedView = [self hitTest:yourLocation forEvents:nil];
This will return you the view which is tapped
Check this with if condition like this
if(tappedView == Imageview)
{
// do this
}
else if(tappedView == CollectionViewCell)
{
// do this
}

Related

How to detect touches on UIView of UITableViewCell with more then one section?

I found already some solution how to detect touch in my cell, but they are made for one section. I have more then 1(8 tbh). Following code are making touch for few cells instead of one. So question is, what the clear solution to my problem? Here the code:
- (CatalogItemTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CatalogItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
CatalogItemModel *currentItemModel;
if(isCatSelected) {
currentItemModel = [[self.itemsArray objectForKey:[[self.sectionArray objectAtIndex:selectedIndexPath] valueForKey:#"id"]] objectAtIndex:indexPath.row];
} else {
currentItemModel = [[self.itemsArray objectForKey:[[self.sectionArray objectAtIndex:indexPath.section] valueForKey:#"id"]] objectAtIndex:indexPath.row];
}
[cell setItemModel:currentItemModel];
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(didTapFav:)];
[cell.overFavorite addGestureRecognizer:gestureRecognizer]; //overFavorite is UIView to detect touch
return cell;
}
Action func:
-(void)didTapFav:(UITapGestureRecognizer*)recognizer {
NSString *token = [ProfileManager getToken];
if(token.length > 0){
[[NSNotificationCenter defaultCenter] postNotificationName:#"addToFavorite" object:self];
} else {
[self showErrorWithTitle:#"Auth" andText:#"To add item in Favorite!"];
}
}
Function inside CatalogItemTableViewCell:
-(void)addToFavorite {
if(isFavorite) {
[ApiManager tryAddToFavItem:[NSString stringWithFormat:#"%ld", (long)self.currentModel.uid] :^{
//Some API request
}];
}
}
First of all add gestureRecognizer for your CollectionView
UIGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tap:)];
tapGesture.delegate = self;
[self.collectionView addGestureRecognizer:tapGesture];
then get the IndexPath or Cell you want to access in - (void)tap:(UITapGestureRecognizer* )sender;
if (sender.state == UIGestureRecognizerStateEnded) {
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[sender locationInView:self.collectionView]];
}

Delete UICollectionViewCell with UILongPressGestureRecognizer

I have a UICollectionView that I populate from my Image Library.
I want to be able to delete a cell from the collection by using a UILongPressGestureRecognizer on the cell. The UILongPressGestureRecognizer is working.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected cell = %ld",(long)indexPath.item);
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(activateDeletionMode:)];
longPress.delegate = self;
[collectionView addGestureRecognizer:longPress];
}
- (void)activateDeletionMode:(UILongPressGestureRecognizer *)gr
{
if (gr.state == UIGestureRecognizerStateBegan)
{
NSLog(#"delete mode");
}
}
In your case try this
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected cell = %ld",(long)indexPath.item);
UILongPressGestureRecognizer * longPres
= [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(activateDeletionMode:)];
longPres.minimumPressDuration = .5; //seconds
longPres.delegate = self;
[self.collectionView addGestureRecognizer: longPres];
}
- (void)activateDeletionMode:(UILongPressGestureRecognizer *)gr
{
if (gr.state == UIGestureRecognizerStateBegan)
{
NSLog(#"delete mode");
}
}
in other case you can try this
//add long press gesture to collectionView
UILongPressGestureRecognizer *longpress
= [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongpressMethod:)];
longpress.minimumPressDuration = .5; //seconds
longpress.delegate = self;
[self.collectionView addGestureRecognizer: longpress];
}
then handle the action
-(void) handleLongpressMethod:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
return;
}
CGPoint pt = [gestureRecognizer locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:pt];
if (indexPath == nil){
NSLog(#"couldn't find index path");
} else {
// get the cell at indexPath (the one you long pressed)
UICollectionViewCell* cell =
[self.collectionView cellForItemAtIndexPath:indexPath];
// work with the cell
}
delete
[self.youritemarray removeObjectAtIndex:indexPathh];
[collectionView reloadData];

How to use swipe to change the label of specific row in tableview

In ViewDidLoad of table view controller, I first added SwipeGuesture and handler "Swipecell"
UISwipeGestureRecognizer *showExtrasSwipe = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(Swipecell:)];
showExtrasSwipe.direction = UISwipeGestureRecognizerDirectionRight|
UISwipeGestureRecognizerDirectionLeft;
[self.tableView addGestureRecognizer:showExtrasSwipe];
//Here I define the handler:
-(void)Swipecell:(UISwipeGestureRecognizer *)gesture
{
//Taking gesture location
CGPoint location = [gesture locationInView:_tableview];
//Getting IndexPath for that location in tableview
NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
NSString *data = [self.dataArray objectAtIndex:swipedIndexPath.row];
//Setting the label of the cell
[swipedCell.textLabel setText:data];
}
But it is working only for one first row. Can anybody help me in this or give me better solution? Don't forget to rate, if you like the question.
Please add the swipe gesture in cellForRowAtIndexPath method , so the gesture will be added to each cell.
It works... Tested on iOS 7.1 simulator
- (void)viewDidLoad
{
_tableview = (UITableView*)self.view;
[super viewDidLoad];
UISwipeGestureRecognizer *showExtrasSwipe = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(Swipecell:)];
showExtrasSwipe.direction = UISwipeGestureRecognizerDirectionRight|
UISwipeGestureRecognizerDirectionLeft;
[self.tableView addGestureRecognizer:showExtrasSwipe];
}
-(void)Swipecell:(UISwipeGestureRecognizer *)gesture
{
CGPoint location = [gesture locationInView:_tableview];
NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
swipedCell.detailTextLabel.text = [NSString stringWithFormat:#"%i", swipedIndexPath.row];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 55;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.textLabel.text = [NSString stringWithFormat:#"%i", indexPath.row];
cell.detailTextLabel.text = #" ";
return cell;
}
Change [gesture locationInView:_tableview] to [gesture locationInView:self.tableview]. I was refering to tableView outlet.

Making UITextField in prototype cell first responder

I have set up the textfield with a tag and user interaction disabled in a prototype cell.
This is how I have created the cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
..
..
..
UILongPressGestureRecognizer *longPressgesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(LongPressgesture:)];
[longPressgesture setMinimumPressDuration:2.0];
[cell.contentView addGestureRecognizer: longPressgesture];
UITextField *toDoTextField = (UITextField *)[cell.contentView viewWithTag:1];
toDoTextField.tag = indexPath.row;
return cell;
}
then I would like to edit the textfield after a long press. So I have this:
- (void)LongPressgesture:(UILongPressGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded) {
}
else {
UITableView* tableView = (UITableView*)self.view;
CGPoint touchPoint = [recognizer locationInView:self.view];
NSIndexPath* row = [tableView indexPathForRowAtPoint:touchPoint];
NSInteger rowRow = [row row];
UITextField *toDoTextField = (UITextField *)[cell.contentView viewWithTag:rowRow];
toDoTextField.userInteractionEnabled = YES;
[toDoTextField becomeFirstResponder];
}
When I trigger the long press though only the last cell will work. Not sure what I'm doing wrong.
I would like to be able to long press on any cell and then edit the text.
Thank you if you can help.
Add the long press gesture recognizer to the table view not the cell:
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
recognizer.minimumPressDuration = 2.0;
[self.myTableView addGestureRecognizer:recognizer];
Then handle it like this:
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
if (recognizer.state != UIGestureRecognizerStateEnded)
return;
CGPoint p = [gestureRecognizer locationInView:self.myTableView];
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
if (!indexPath)
NSLog(#"Long press was on tableView, but not on a row");
else
{
NSLog(#"Long press on table view # row %d", indexPath.row);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
NSAssert(cell, #"Cell must be found");
if (!cell)
return;
UITextField *toDoTextField =
(UITextField *)[cell.contentView viewWithTag:indexPath.row];
NSAssert(toDoTextField, #"UITextField must be found by tag");
if (toDoTextField)
{
[self.tableView endEditing:YES];
toDoTextField.userInteractionEnabled = YES;
[toDoTextField becomeFirstResponder];
}
}
}

UITapGestureRecognizer on UIImageView within UITablevlewCell not getting called

I currently have a custom UITableViewCell which contains a UIImageView and trying to add a UITapGestureRecognizer on the UIImageView with no luck. here is snippet of the code.
//within cellForRowAtIndexPath (where customer table cell with imageview is created and reused)
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
tap.delegate = self;
[imageView addGestureRecognizer:tap];
[tap release];
// handle method
- (void) handleImageTap:(UIGestureRecognizer *)gestureRecognizer {
RKLogDebug(#"imaged tab");
}
I've also set userInteractionEnabled on the cell and the superview of the UIImageView but still no luck, any hints?
EDIT:
I've also remove cell's selection by cell.selectionStyle = UITableViewCellSelectionStyleNone; Could this be a problem
UIImageView's user interaction is disabled by default. You have to enable it explicitly to make it respond to touches.
imageView.userInteractionEnabled = YES;
Swift 3
This worked for me:
self.isUserInteractionEnabled = true
In my case it looks like :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = CELL_ROUTE_IDENTIFIER;
RouteTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[RouteTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
if ([self.routes count] > 0) {
Route *route = [self.routes objectAtIndex:indexPath.row];
UITapGestureRecognizer *singleTapOwner = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(imageOwnerTapped:)];
singleTapOwner.numberOfTapsRequired = 1;
singleTapOwner.cancelsTouchesInView = YES;
[cell.ownerImageView setUserInteractionEnabled:YES];
[cell.ownerImageView addGestureRecognizer:singleTapOwner];
} else {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
And selector :
- (void)imageOwnerTapped:(UISwipeGestureRecognizer *)gesture {
CGPoint location = [gesture locationInView:self.tableView];
NSIndexPath *tapedIndexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *tapedCell = [self.tableView cellForRowAtIndexPath:tapedIndexPath];
NSIndexPath *indexPath = [self.tableView indexPathForCell:tapedCell];
NSUInteger index = [indexPath row];
Route *route = [self.routes objectAtIndex:index];
}

Resources