How to pause/disable UILongPressGestureRecognizer on a UITableViewCell while in editmode - iphone

In a tableview I have on every cell a UILongPressGestureRecognizer which I add like this:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(TableCellLongPressed:)];
longPress.minimumPressDuration = 0.5f;
[cell addGestureRecognizer:longPress];
[longPress release];
Now I do have the following problem I want the user to be able to rearrange the cell in the tableview so I have a button that sets the tableView to EditMode like this:
[self.myTableView setEditing:!self.myTableView.editing animated:YES];
Now when the user tries to drag a cell and does not drag it far enough the longPress fires his action which is very annoying for the user cause another view gets pushed.
How can I pause or disable the UILongPressGestureRecognizer when the tableView is in EditMode?

You should implement the UIGestureRecognizerDelegate delegate for this method:
gestureRecognizer:shouldReceiveTouch:
In the method, check if you're editing the table and return NO if you are.
Tim

Related

Adding single and double tap gesture on subview of UITableViewCell

I have a UIImageView in UITableViewCell. I am trying to add Single Tap gesture to view it in full size and double tap gesture to like. Here is my code for that:
UITapGestureRecognizer *aSingleTapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(SingleTapGestureRecognizer:)] autorelease];
aSingleTapGesture.delegate = self;
aSingleTapGesture.numberOfTapsRequired = 1;
[cell.imgProductImage addGestureRecognizer:aSingleTapGesture];
UITapGestureRecognizer *aDoubleTapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapGestureRecognizer:)] autorelease];
aDoubleTapGesture.delegate = self;
aDoubleTapGesture.numberOfTapsRequired = 2;
[cell.imgProductImage addGestureRecognizer:aDoubleTapGesture];
It only calls single tap gesture and double tap gesture was never being called. Than I used require to fail on single tap gesture.
[aSingleTapGesture requireGestureRecognizerToFail:aDoubleTapGesture];
Well, using this code I am able to call single and double tap gesture both, But the problem is the tableView:didSelectRowAtIndexPath: is also being called. I don't want to call didSelectRowAtIndexPath if my gestures are being called. As of my understanding it is being called because single tap gesture is waiting for double tap gesture mean while didSelectRowAtIndexPath is being called.
Any help please.
You can use UIButton instead of UIImageView in tableview cell. Use following code for getting single and double tap.
//add target for your UITableViewCell's button
[aBtnThumbObj addTarget:self action:#selector(btnThumbClickDouble:) forControlEvents:UIControlEventTouchDownRepeat];
[aBtnThumbObj addTarget:self action:#selector(btnThumbClickSingle:) forControlEvents:UIControlEventTouchUpInside];
-(void)btnThumbClickSingle:(UIButton*)sender
{
[self performSelector:#selector(singleTapOnButtonSelector:) withObject:sender afterDelay:0.2];
}
-(void)btnThumbClickDouble:(UIButton*)sender
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(singleTapOnButtonSelector:) object:sender];
//Your implementation for double tap
}
-(void)singleTapOnButtonSelector:(UIButton*)sender
{
//Your implementation for single tap
}
You can set selection style for your cell as
cell.selectionStyle = UITableViewCellSelectionStyleNone;
And then just don't implement your -tableViewDidSelectRowAtIndexPath method
These two lines of code work for me:
tapGesture.cancelsTouchesInView = YES;
tapGesture.delaysTouchesBegan = YES;

iPhone scroll UITableview by swiping out side the table view

In my case I have UIView and UITableView controller. What I want is to scroll the table view by swiping the UIView. I have added swipe up and swipe down gestures for the UIView. When I swipe on this view, scroll the table view along the direction of swipe. Is it posible?
Call this method from your viewDidLoad.
This method will disable the scrolling of the tableview to prevent manual scrolling.Assuming that you have 100 rows of height 30 and myview is the view on which have to perform the scrolling. Swipe gestures are added on myview,it is important to set the direction of the swipe
-(void)initialSetup
{
[self.tableView setScrollEnabled:NO];
int numberOfRows=100;
int rowHeight=30;
myview=[[UIView alloc]initWithFrame:CGRectMake(280, 0, 30, numberOfRows*rowHeight)];
[myview setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:myview];
UISwipeGestureRecognizer *swipeDown=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(motion:)];
[swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[myview addGestureRecognizer:swipeDown];
UISwipeGestureRecognizer *swipeUp=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(motion:)];
[swipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[myview addGestureRecognizer:swipeUp];}
The below method will be called when a swipe gesture occurs either swipeUp or swipeDown.
When the method receives a swipeUp gesture it scrolls the last currently visible row in the tableview to the top
When the method receives a swipeDown it scrolls the first currently visible row to the bottom
-(void)motion:(UISwipeGestureRecognizer *)sender
{
if (sender.direction==UISwipeGestureRecognizerDirectionUp) {
[self.tableView scrollToRowAtIndexPath:[self.tableView.indexPathsForVisibleRows objectAtIndex:[self.tableView.indexPathsForVisibleRows count]-1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}else if(sender.direction==UISwipeGestureRecognizerDirectionDown)
{
[self.tableView scrollToRowAtIndexPath:[self.tableView.indexPathsForVisibleRows objectAtIndex:0 ] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
//let myView be the view from which you want to scroll your tableview(myTableview)
//now add the following lines in your viewdidload method
UISwipeGestureRecognizer * swipegesture = [[UISwipeGestureRecognizer alloc]init];
swipegesture =[myTableview.gestureRecognizers objectAtIndex:1];
[myView addGestureRecognizer:swipegesture];

UITextView Subclass tap to didSelectRowAtIndexPath

I have a UITextView subclass that has an NSIndexPath property that is inside a UITableViewCell. When you tap on it, I'd like to be able to call didSelectRowAtIndexPath.
Here's what I have:
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:nil];
[theTextView addGestureRecognizer:singleFingerTap];
singleFingerTap.delegate = self;
....
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CustomTextView *theTextView = (CustomTextView *)touch.view;
NSLog(#"%#", theTextView.indexPath);
return YES;
}
I see from this question, I may even have to break up my didSelectRowAtIndexPath logic, which is fine. And I already know the index path of the view that was tapped.
What is the proper way to call this tableView method (or what didSelectRowAtIndexPath would do) from within the gesture recognizer method?
I answered a similar question here. Basically when you call:
[tableView selectRowAtIndexPath:path animated:YES scrollPosition:UITableViewScrollPositionNone];
the tableview doesn't fire the tableView:didSelectRowAtIndexPath: on the tableview's delegate, so in addition you are forced to directly call (And since you wrote the code in the delegate method there's no problem):
[tableView.delegate tableView:tableView didSelectRowAtIndexPath:path];
Also your passing nil for the action is really not how gesture-recognizers where mean to work:
[[UITapGestureRecognizer alloc] initWithTarget:self action:nil];
Generally you would do something like this:
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecognized:)];
That basically tells the gesture recognizer to call the tapRecognized: method when it receives a tap. So basically to wrap it all up (I'm assuming this is in a UITableViewController or an object with a property named tableView as UITableViewControllers have by default).
-(void)tapRecognized:(UITapGestureRecognizer *)tapGR{
// there was a tap
CustomTextView *theTextView = (CustomTextView *)tapGR.view;
NSIndexPath *path = theTextView.indexPath;
[self.tableView selectRowAtIndexPath:path animated:YES scrollPosition:UITableViewScrollPositionNone];
[self.tableView.delegate tableView:self.tableView didSelectRowAtIndexPath:path];
}
If you need to do X both in response to a gesture and to a tap on a table view row, simply create a method X and call that from your gesture recognizer method as well as from your didSelectRowAtIndexPath table view delegate method.
Of course, theoretically,
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
would work, but I think calling the delegate method yourself is bad style to say the least.

Custom touch area on tableview cell with checkbox iphone

I've added a checkbox to a table view cell which is a custom button with two images. Clicking this works fine as I can check and uncheck.
The problem is when you click the rest of the row it still selects the checkbox/button. If I comment out didSelectRowAtIndexPath it doesn't happen so I'm wondering how to get around this happening?
A solution I'd be happy with is to allow only selection of the Accessory Disclosure Indicator but there doesn't seem to be a way of doing this.
Sorry if this is a really badly asked question, I'm very tired! Let me know if you need code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WedAppDelegate *delegate = (WedAppDelegate *)[[UIApplication sharedApplication] delegate];
PlanTaskShowViewController *planTaskShowViewController = [[PlanTaskShowViewController alloc] initWithNibName:#"PlanTaskShowViewController" bundle:nil];
[delegate.navController pushViewController:planTaskShowViewControlleranimated:YES];
[planTaskShowViewController release];
}
put an button on the front instead of an image and do the selecting thing only when button is clicked (change the image of the button).
OR
put an on click event listener / gesture recognizer on your image
UITapGestureRecognizer *singleFingerDTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(changeImage:)];
[imageView addGestureRecognizer:singleFingerDTap];
[singleFingerDTap release];
//EDIT:
If you use highlightedImage for your UIImageView or UIButton it will be highlighted when selecting the UITableViewCell. It's a really nice feature, but sometimes it's only confusing ;)
Check this :
UITapGestureRecognizer *singleFingerDTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(changeImage:)];
[imageView addGestureRecognizer:singleFingerDTap];
[singleFingerDTap release];

Do I need to release a gesture recognizer?

If I add a gesture recognizer to a table cell called cell, e.g.:
UILongPressGestureRecognizer *_longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(cellGestureRecognized:)];
_longPressRecognizer.allowableMovement = 20;
_longPressRecognizer.minimumPressDuration = 1.0f;
[cell addGestureRecognizer:_longPressRecognizer];
[_longPressRecognizer release], _longPressRecognizer = nil;
Do I need to manually call -removeGestureRecognizer: on this cell at some point, or does the gesture recognizer get removed and released for me when the cell is no longer used?
The gesture recognizers are added to an internal NSMutableArray of the view. This array will be released once the view is deallocated. Thus -removeGestureRecognizer: doesn't need to be called manually.