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
Related
I have added a textfield in oe of the cell in my tableview.
Now I want to compare if the touched object is textfield or not. For that I am using -
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event
{
UITouch *touch = [[event allTouches] anyObject];
}
method. Here I have to get the view touched in UITableview cell is textfield.
How can I get that? I am struct at this. Please help.
Use TextField Delegate method :
-(void)textFieldDidBeginEditing:(UITextField *)textField
I think the best way to achieve this would be:
Create a UITableViewCell subclass with a UITextField as a subview. Define it as an IBOutlet and hook it up via interface builder.
Create a delegate protocol to notify a delegate (in your case it could be the same class handling the UITableViewDataSource) of this event.
Declare the UITableViewCell subclass as a UITextFieldDelegate and hook it up to the UITextField you've created. via IB
Implement
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[self.delegate textFieldWasTapped];
}
Now you'll be notified in the main controller of a textFieldWasTapped event. There's no need to check if it indeed came from a UITextField object because only instances if this type will be able to trigger this call.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event
{
UITouch *touch = [[event allTouches] anyObject];
if([[touch view] isKindOfClass:[UITextField class]])
{
UITextField *txtField = (UITextField *) [touch view];
//UITextField object
}
}
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…
I am trying to find out the location of a swipeGesture when swiped on a tableview.
In the swipe action, I've seen many people do this:
CGPoint location = [recognizer locationInView:tableView];
NSIndexPath* indexPath = [tableView indexPathForRowAtPoint:location];
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
But my tableView is made up of section headers that have no cells in them. Because of that, the index path method returns nil. Is there any way to find the location of the Section header? They don't have this method, but something like indexPathForSectionAtPoint: would be the kind of thing I'm looking for.
If anybody knows how to do this, it would be greatly appreciated.
Thanks,
You already have the location and the indexPath.
Now, to get the cell (and its data) you use indexPath.row, as in your example.
To get the section (with or without cell) you use indexPath.section.
If there is no row beneath the point location indexPathForRowAtPoint: will return nil, so that is expected behavior.
Section headings are not really meant to be areas of the view for interaction. Rather they are headings. The UITableView is designed to respond to interaction with its rows.
Maybe one way to fix this is to change your data structure so that the content you display in your section headings really lives in table view rows.
Another approach would be to use the UIView of the section header and have it respond to the swipe gesture. (Make sure you pass the gesture on to the table view with super.)
Ended up doing something similar, but with a tap gesture on the table section header (instead of swipe).
There are probably more elegant ways to do this, but I basically convert the gesture's view to the tableView coordinate space. Then I iterate over each section header's CGRect to see if it intersects with the gesture origin.
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCellWithIdentifier("header") as! HeaderCell
let tapHeader = UITapGestureRecognizer(target: self, action: "tappedOnHeader:")
tapHeader.delegate = self
tapHeader.numberOfTapsRequired = 1
tapHeader.numberOfTouchesRequired = 1
cell.contentView.addGestureRecognizer(tapHeader)
return cell
}
func tappedOnHeader(gesture:UIGestureRecognizer){
if let cellContentView = gesture.view {
let tappedPoint = cellContentView.convertPoint(cellContentView.bounds.origin, toView: tableView)
for i in 0..<tableView.numberOfSections {
let sectionHeaderArea = tableView.rectForHeaderInSection(i)
if CGRectContainsPoint(sectionHeaderArea, tappedPoint) {
print("tapped on section header:: \(i)")
}
}
}
}
Created a git branch on another tutorial project as a working example:
https://github.com/ThornTechPublic/HorizontalScrollingCollectionView/tree/sectionHeaderTap
//Sublcass a header footer view and in .h file declare this protocol
#protocol MyProtocol <NSObject>
-(void)userTappedView:(UITableViewHeaderFooterView *)view atPoint:(CGPoint)point;
#end
//in same .h file add this
#property (weak, nonatomic) id <MyProtocol> delegate;
//In same subclass .m file do this
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint point = [touch locationInView:self];
[self.delegate userTappedView:self atPoint:point];
}
//In controller containing tableview, conform to 'MyProtocol' like this
-(void)userTappedView:(UITableViewHeaderFooterView *)view atPoint:(CGPoint)point {
NSNumber *value = [self sectionForUserSelectionInTableView:self.tableView
atTouchLocation:point
inHeaderFooterView:view];
if (!value) {
return;
}
NSUInteger tappedSection = value.integerValue;
}
-(NSNumber *)sectionForUserSelectionInTableView:(UITableView *)tableView
atTouchLocation:(CGPoint)location
inHeaderFooterView:(UITableViewHeaderFooterView *)view {
CGPoint point = [tableView convertPoint:location
fromView:view];
for (NSInteger i = 0; i < [tableView numberOfSections]; i++) {
CGRect rect = [tableView rectForHeaderInSection:i];
if (CGRectContainsPoint(rect, point)) {
return #(i);
}
}
return nil;
}
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;
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]];
...
}