how to detect touch event in table cells for iphone - iphone

how to detect touch event for table cells
i tried this
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//<my stuff>
[super touchesBegan:touches withEvent:event];
}
but its not working actuallly i have aUIimage view in table cell and i want to chnage imgae based on tap so my touch event is not working for that cell

If you want to detect a touch on the UITableViewCell you don't really need to detect touch events. In your UITableViewController subclass, you need to implement the following delegate method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
Then you modify the image of the table cell for the selected index path.

You probably need to set myImageView.userInteractionEnabled = YES;.

In one of my projects I needed any tap on the tableView to dismiss the keyboard so the underlying tableView would show. Since a UITableView is really a UIScrollView, it will respond to the scrollView delegate methods. Using these 2 methods will dismiss if either the user taps on a cell or scrolls the tableView at all:
IMPORTANT: Make sure you implement the UIScrollViewDelegate in your .h file as well as the UITableViewDelegate and UITableViewDataSourceDelegate!!!
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//remove keyboard if table row is clicked
if ([self.firstName isFirstResponder] || [self.lastName isFirstResponder]) {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
[self.firstName resignFirstResponder];
[self.lastName resignFirstResponder];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
//remove keyboard if table scrolls
if ([self.firstName isFirstResponder] || [self.lastName isFirstResponder]) {
[self.firstName resignFirstResponder];
[self.lastName resignFirstResponder];
}
}

Related

Why does UITableView's swipe delete sometimes work fine & sometimes not?

There is a UITableView on my view, I want to apply swipe-delete-mode rows of a certain section. What I have implemented is as follows:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#">> canEditRowAtIndexPath");
if (indexPath.section == CanDeletedSection) {
return YES;
}else{
return NO;
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#">> editingStyleForRowAtIndexPath");
if (indexPath.section == CanDeletedSection) {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#">> commitEditingStyle");
if (editingStyle == UITableViewCellEditingStyleDelete) {
// dosomething
}
}
But when I swipe the table row, sometimes the Delete button appears, sometimes not.
Incidentally, my cell is customized and inherits from UITableViewCell.
I have added the NSLog to above methods. When the Delete button not appears the log I got like this:
>> editingStyleForRowAtIndexPath
>> canEditRowAtIndexPath
When the Delete button appears, the log as below:
>> editingStyleForRowAtIndexPath
>> canEditRowAtIndexPath
>> editingStyleForRowAtIndexPath
>> canEditRowAtIndexPath
>> canEditRowAtIndexPath
>> editingStyleForRowAtIndexPath
I have made a demo that using the customized cell, it works fine. So the problems are caused by the view controller which contains the table view. The view controller inherits from another view controller, in that view controller, there is a tap gesture which used to hide the keyboard. But when I removed them from the view controller, the result is same.
Please check whether view or superview has any other gestures. If so, make sure that you implement below method of UIGestureRecognizerDelegate after setting gesture delegate:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Sometimes, especially in the simulator, it is difficult to perform the swipe correctly. You will find that it is most likely a physical, not a coding problem.
Also, you might want to check if you custom cell does not contain an element that catches the swipe and does not pass it on to the cell.
I have also faced this same issue...
But finally I got solution by :- Example:-
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
You have to Disable any other gesture in that particular view if you are using "commitcommiteditingstyle"..
Hope this will help you... :)
Gesture recognizers elsewhere in the view hierarchy can intercept and block the swipe action.
I solved it with this category in the view controller:
#interface UIView (CellSwipeAdditions)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
#end
#implementation UIView (CellSwipeAdditions)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
#end
Thanks to bademi for leading me to this solution!

Detect which side of uitableviewcell has been click: left or right

Is it possible to distinguish which side of a row in a uitableview has been clicked?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//which side of row has been detected left or right
}
You can subclass UITableViewCell. In your subclass, you can make an iVar wasTouchOnLeft. Then override touchesBegan or touchesEnded like the example below:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch=(UITouch *)[touches anyObject];
if([touch locationInView:self].x< (0.5 * self.frame.size.width) )
{
NSLog(#"Touched Left");
wasTouchOnLeft=YES;
}
else {
NSLog(#"Touched Right");
wasTouchOnLeft=NO;
}
[super touchesEnded:touches withEvent:event];
}
In the didSelectRowAtIndexPath of your UITableViewController you can then access the wasTouchOnLeft variable for the cell.
You can't determine this directly in this method.
But if you really want this feature create a custom tableview cell that has two big buttons (one left one on the right side) or apply a touch recognizer on the cell.
If you have this delegate the action to your controller
(You could also store it in the cell and access it via)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(((YourCustomTableCell*)[tableView cellForRowAtIndexPath:indexPath]).clickedSideProperty) action;
else anotherAction;
}
But better delegate it from the table cell than access it from didSelectRow…

how to begin moving cell with long press gesture?

I have a UITableView with several UITableViewCells in it. I'd like to long press on a cell to begin move it and keep holding on it and drag to move it. But i don't know how.
I added a long press gesture on table view, when user long pressed , set tableview's editing to YES:
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleTableViewLongPress:)];
[_tableView addGestureRecognizer:longPressRecognizer];
- (void)handleTableViewLongPress:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state != UIGestureRecognizerStateBegan)
return;
[_tableView setEditing:YES];
}
And the tableview could move cell with two methods:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
//update datasource
}
But with these code user must use two touch to move a cell: one is to set the tableview to editing state, another is to move cell. What i want is to allow user use one touch to do this.
Any suggestions? thanks!
I have found this UITableView subclass: Move table view

Showing UIMenuController loses keyboard

I'm making an iphone app similar to the Messages app that comes on the phone. I just set up the ability to copy messages via a UIMenuController, but if the keyboard is showing and someone tries to copy a message, the keyboard goes away (presumably because of my [cell becomeFirstResponder]; where cell is the message cell being copied).
Is there a way to show the Copy message without losing the keyboard?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath {
//...other cell setup stuff...
UILongPressGestureRecognizer *longPressGesture =
[[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(showCopyDialog:)];
[cell addGestureRecognizer:longPressGesture];
return cell;
}
- (void)showCopyDialog:(UILongPressGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan)
{
ConvoMessageCell *cell = (ConvoMessageCell *)[gesture view];
NSIndexPath *indexPath = [self.tblConvo indexPathForCell:cell];
UIMenuController *theMenu = [UIMenuController sharedMenuController];
[cell becomeFirstResponder];
[theMenu setTargetRect:CGRectMake(menuX, menuY, 100, 100) inView:cell];
[theMenu setMenuVisible:YES animated:YES];
}
}
I solved this dilemma by subclassing UITextView to provide a way to override the nextResponder and disable the built-in actions (Paste), like so:
#interface CustomResponderTextView : UITextView
#property (nonatomic, weak) UIResponder *overrideNextResponder;
#end
#implementation CustomResponderTextView
#synthesize overrideNextResponder;
- (UIResponder *)nextResponder {
if (overrideNextResponder != nil)
return overrideNextResponder;
else
return [super nextResponder];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if (overrideNextResponder != nil)
return NO;
else
return [super canPerformAction:action withSender:sender];
}
#end
Then, in your gesture action handler, check whether the text view is already the first responder. If so, have it override the next responder; otherwise the keyboard is probably hidden anyway and you can simply becomeFirstResponder. You'll also have to reset the override when the menu hides:
if ([inputView isFirstResponder]) {
inputView.overrideNextResponder = self;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(menuDidHide:)
name:UIMenuControllerDidHideMenuNotification object:nil];
} else {
[self becomeFirstResponder];
}
- (void)menuDidHide:(NSNotification*)notification {
inputView.overrideNextResponder = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIMenuControllerDidHideMenuNotification object:nil];
}
Using the table view delegate methods introduced in iOS 5 (shouldShowMenuForRowAtIndexPath etc.) wasn't a solution for me as I needed control over the positioning of the menu (by default it's simply horizontally centered over the cell, but I'm displaying message bubbles and wanted the menu centered over the actual bubble).
In iOS 5, you can now use the table view delegate methods to show the Menu Controller:
- (BOOL) tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender;
Showing the Menu Controller in this manner will not resign the keyboard.
I'm still curious about this though as I have an app that supports pre-iOS 5 that I would like to do what you're saying also (not resign the keyboard when the copy menu appears).

Enable AccessoryDetailButton even if cell is disabled

I want to have my UITableViewCell disabled but still be able to press the accessoryView button.
I thought this would work:
cell.userInteractionEnabled = NO;
cell.accessoryView.userInteractionEnabled = YES;
But my UITableViewCellAccessoryDetailDisclosureButton is still disabled.
accessoryView will get all his touchEvents from his superview, in this case your cell and wont react to your actions.
What might work is creating a touch event to that accesoryView on the viewController you make the tableView on and make it react to touches.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
UITouch *touch = [[event allTouches] anyObject];
if ([touch view] == accessoryView) {
//do something because you hit accessoryView
}
}
If you disable a view, all its subviews will be disabled.
For this you have to set userInteractionEnabled =NO all subviews in cell expect in Disclosure and cell.
cell.selectionStyle=UITableViewCellSelectionStyleNone;
cell.userInteractionEnabled = YES;
Place this line in this method.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Leave this method blank. if u want to code in this delegate method so filter those row by code:
if(indexPath.row == row no in which u don't want click event)
{
leave blank
}
else
{
code which u want .
}
}
you get your click event for particular button in this method.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;