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

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…

Related

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;

UIScrollView inside UITableViewCell touch detect

I have a tableview with 8 custom cells. in the 8th cell I added a scrollView with paging enabled so I can show page 1 and page 2 (or 3, 4... 10) without have a very high cell.
The problem is with the scrollView I can't use didSelectRowAtIndexPath because the cell is behind the scrollView so I'm trying to detect scrollView tap (not swipe).
I played with touchesBegan and touchesEnded but they are never called (I know touches work with UIView only, but maybe.....)
Any help is very appreciated.
Thanks,
Max
There is a trick Apple recommends to use in this case, in theirs WWDC 2014 session "Advanced scrollviews" (See Demo starting from 8:10):
[cell.contentView addSubview:_scrollView];
[_scrollView setUserInteractionEnabled:NO];
[cell.contentView addGestureRecognizer:_scrollView.panGestureRecognizer];
That's all what needs to be done, no need to override touchesBegan:, touchesMoved: and others.
I used solution based on overriding of touchesBegan:, touchesMoved:, touchesEnded: and touchesCancelled: previously, but sometimes it caused a weird behaviour: when select a certain cell, method -tableView:didSelectRowAtIndexPath: was called for cell with different indexPath.
Solution from Apple has no side effects so far and looks more elegant.
There is also an elegant resolution:
Create a SubClass from UIScrollView and override the following methods
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesMoved:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesCancelled:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self superview]touchesEnded:touches withEvent:event];
}
Passing every touch to the superview of the scroll view and then the didSelectRowAtIndexPath will be called.
Solved subclassing both uitableviewcell and uiscrollview.
It worked for my needs. Hope it can help.
Max
myScrollView.h
#import <UIKit/UIKit.h>
#interface myScrollView : UIScrollView {
}
#end
myScrollView.m
#import "myScrollView.h"
#implementation myScrollView
- (id)initWithFrame:(CGRect)frame {
return [super initWithFrame:frame];
}
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event
{
NSLog(#"touch scroll");
// If not dragging, send event to next responder
if (!self.dragging)
[self.nextResponder touchesEnded: touches withEvent:event];
else
[super touchesEnded: touches withEvent: event];
}
myCell.h
#import <UIKit/UIKit.h>
#interface myCell : UITableViewCell {
}
#end
myCell.m
#import "myCell.h"
#implementation myCell
- (id)initWithFrame:(CGRect)frame {
return [super initWithFrame:frame];
}
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event
{
NSLog(#"touch cell");
// If not dragging, send event to next responder
[super touchesEnded: touches withEvent: event];
}
RootViewController.h
#import <UIKit/UIKit.h>
#class myCell;
#class myScrollView;
#interface RootViewController : UITableViewController {
myCell *cell;
myScrollView *scrollView;
}
#end
RootViewController.m
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
// my custom cell
cell = [[myCell alloc] init];
if (cell == nil) {
cell = [[[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// the custom scroll view
scrollView = [[myScrollView alloc] initWithFrame:cell.frame];
scrollView.contentSize = CGSizeMake(640, 40);
[cell.contentView addSubview:scrollView];
//something to add in scrollView
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 20)];
label.text = #"some text";
[scrollView addSubview:label];
// Configure the cell.
return cell;
}
The selected answer is correct, but I updated the code based on a bug I was getting.
In the subclassed scroll view add the following code.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (self.dragging) {
[super touchesMoved:touches withEvent:event];
} else {
if ([self.delegate isKindOfClass:[UITableViewCell class]]) {
[(UITableViewCell *)self.delegate touchesCancelled:touches withEvent:event];
}
[self.superview touchesMoved:touches withEvent:event];
}
}
If your self.delegate is not the UITableViewCell, than replace that property with a property to your cell.
The cell needs to retrieve the cancel touch event during movement to prevent the undesired results. It can be easily reproducible as follows.
Highlight the cell (assuming the scroll view is over the whole cell, if not highlight the scroll view)
While the cell is highlighted, drag the table view
Select any other cell and now the previously highlighted cell will retrieve the didSelectCell state
Another point to mention is that order matters! If the self.delegate is not called before the self.superview then the highlighted state wont happen.
I found the simplest solution for my needs:
subclass UIScrollView touchesEnded method and post a notification.
In the UITableview add an observer in viewdidAppear (remove it in viewdiddisappear) to call a function that call tableview didSelectRowForIndexPath.
Something like this (swift version)
// myScrollView.swift
import UIKit
class myScrollView: UIScrollView {
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
NSNotificationCenter.defaultCenter().postNotificationName("selectTVRow", object: nil)
}
}
In your tableView:
// ItemsList.swift
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "selectFourthRow", name: "selectTVRow", object: nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "selectfourthrow", object: nil)
}
func selectFourthRow() {
let rowToSelect:NSIndexPath = NSIndexPath(forRow: 4, inSection: 0);
self.tableView(self.tableView, didSelectRowAtIndexPath: rowToSelect);
}
/*
.... rest of your tableview Datasource and Delegate methods...
numberOfSectionsInTableView, numberOfRowsInSection, cellForRowAtIndexPath
*/

touchBegan in a TableView

I use touchesBegan:withEvent: to get the touches of the user in the screen but when i touch a cell in a tableView this method didn't get the tag that i give the view.and the x and y are from the cell and not from the all screen.
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
UITouch *touch = [[touches allObjects] objectAtIndex:0];
CGPoint finger = [touch locationInView:self];
int x = finger.x;
int y = finger.y;
}
This is the touchesBegan:withEvent: method. there is any way to fix it?
You should use this method :
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
It is a delegate method, so don't forget to connect your delegate and datasource in Interface Builder .
Apple Documentation - UITableViewDelegate

how to detect touch event in table cells for 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];
}
}

UITableViewController and detecting touches

I have a UITableViewController and want to detect touches.
Basically, I want the user to be able to hold down a touch for 3 seconds, when they let go I want to pop up a small view with a few options for the table.
I've tried this...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.lastTouch = [event timestamp];
NSLog(#"TLC.touchesBegan:touchBeginEndInterval %f", self.lastTouch);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSTimeInterval touchBeginEndInterval = [event timestamp] - self.lastTouch
NSLog(#"TLC.touchesEnded:touchBeginEndInterval %f %f", self.lastTouch, touchBeginEndInterval);
}
And it isn't picking up my touches at all...
Any ideas about the best way to implement this?
TableViews have sort of a "touch" delegate method. Implement this method for your tableView delegate:
// What happens when a row is touched
- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}
You shouldn't make them press for 3 seconds... just use the standard.
Assuming that code comes from your UITableViewController subclass ... UIViewControllers don't receive methods like touchesBegan:withEvent. Only UIResponders like UIView an its subclasses like UITableView do. So you are trying to get the touches in the wrong place.
What are you trying to accomplish? Do you want to respond to touches in the UITableView or in a UITableViewCell? In case of the latter, you can deal with the touches in your custom cell implementation.
Now it's easy to accomplish with UILongPressGestureRecognizer:
-(void)viewDidLoad{
[super viewDidLoad];
UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressHandlerMethod:)];
[self.tableView addGestureRecognizer:longPressRecognizer];
}
-(void)longPressHandlerMethod:(UIGestureRecognizer *)gestureRecognizer{
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:[gestureRecognizer locationInView:self.tableView]];
...
}