get CGPoint inside didSelectItemAtIndexPath method of CollectionView - ios

Is there a way that I can get coordinates of clicked point inside collectionViewCell? I want to do method A if I clicked at rect with Y coordinate < 50, and method B if Y >50.

There is also option B, to subclass the UITableViewCell and get the location from the UIResponder class:
#interface CustomTableViewCell : UITableViewCell
#property (nonatomic) CGPoint clickedLocation;
#end
#implementation CustomTableViewCell
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
self.clickedLocation = [touch locationInView:touch.view];
}
#end
Then get the location from the TableViewCell it self:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//get the cell
CustomTableViewCell *cell = (CustomTableViewCell*)[tableView cellForRowAtIndexPath:indexPath];
//get where the user clicked
if (cell.clickedLocation.Y<50) {
//Method A
}
else {
//Method B
}
}

Assuming you have a custom UICollectionViewCell, you can add a UITapGestureRecognizer to the cell and get the touch point in the touchesBegan handler. Like this:
//add gesture recognizer to cell
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] init];
[cell addGestureRecognizer:singleTap];
//handler
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
if (touchPoint.y <= 50) {
[self methodA];
}
else {
[self methodB];
}
}

Related

CGPoint of tap on UITableViewCell using touchesBegan

I am needing the CGPoint of a tap on my UITableViewCell. To do this I want to use the touchesBegan:withEvent: method in my subclassed UITableViewCell.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
NSLog(#"%#", NSStringFromCGPoint(location));
}
How can I forward that from my UITableViewCell subclass to my current viewController so that I can make an action depending on where in the cell they tapped?
** I don't want to use a Gesture Recognizer on the cell since it will not allow the didSelectRowAtIndexPath: method to be called.
Either delegation or block call back would do it. Below is an example of using blocks
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
__weak __typeof(self) weakSelf = self;
cell.touchedAtPoint = ^(UITableViewCell *cell, CGPoint point) {
[weakSelf doSomethingWithPoint:point);
};
return cell;
}
In the cell
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
[super touchesBegan:touches withEvent:event];
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
void (^touchedAtPoint)(UITableViewCell *, CGPoint) = self.touchedAtPoint;
if (touchedAtPoint) {
touchedAtPoint(self, location);
}
}
- (void)prepareForReuse;
{
[super prepareForReuse];
self.touchedAtPoint = nil;
}
Declaration of ivar
#property (nonatomic, copy) void (^touchedAtPoint)(UITableViewCell *cell, CGPoint point);

touchesBegan:withEvent: on UIView in UITableViewCell called with noticable delay

I have a UIView that has touchesBegan:withEvent: to handle touches, this UIView is in the UITableViewCell.
When I touch it nothing happens, when I "long press" it then the touch event is trigerred.
Is there a setup I skipped? What can I do to have instant reaction to touch on my UIView?
This is the code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self];
[self handleTouchAtLocation:touchLocation];
}
When I put NSLog to this method, this is what is traced (formatting is mine):
touchesBegan:touches withEvent:<UITouchesEvent: 0x170078f00>
timestamp: 281850 touches: {(
<UITouch: 0x1781486c0>
phase: Began tap
count: 1 window: <UIWindow: 0x145e0ab30;
frame = (0 0; 320 568);
gestureRecognizers = <NSArray: 0x178240720>;
layer = <UIWindowLayer: 0x17802b800>>
view: <CSRateView: 0x145d49850;
frame = (50 54; 220 40);
autoresize = TM;
layer = <CALayer: 0x17003c0c0>>
location in window: {207, 81}
previous location in window: {207, 81}
location in view: {157, 7}
previous location in view: {157, 7}
)}
Disable delaysContentTouches for tableView
self.tableView.delaysContentTouches = NO;
Then, in you cell class:
#implementation MyCell
- (void)awakeFromNib
{
for (id view in self.subviews) {
if ([view respondsToSelector:#selector(setDelaysContentTouches:)]){
[view setDelaysContentTouches:NO];
}
}
}
#end
-- EDIT--
Or make a category on UITableViewCell
#import "UITableViewCell+DelayTouches.h"
#implementation UITableViewCell (DelayTouches)
- (void)setDelayContentTouches:(BOOL)enable
{
for (id view in self.subviews) {
if ([view respondsToSelector:#selector(setDelaysContentTouches:)]){
[view setDelaysContentTouches:enable];
}
}
}
#end
And in cellForRow:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ...
[cell setDelayContentTouches:NO];
return cell;
}

Add condition in macro

How to add following condition in macro
if (![NSStringFromClass([[self superview] class]) isEqualToString:#"_UIModalItemAlertContentView"])
I want to add these two methods only if superClass of tableView category is not alertView
#if ([NSStringFromClass([[self superview] class]) isEqualToString:#"_UIModalItemAlertContentView"])
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.customDelegate respondsToSelector:#selector(tableView:touchBegan:withEvent:)]) {
[self.customDelegate tableView:self touchBegan:touches withEvent:event];
}
[super touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.customDelegate respondsToSelector:#selector(tableView:touchEnded:withEvent:)]) {
[self.customDelegate tableView:self touchEnded:touches withEvent:event];
}
}
#endif
#define YourMacroName(_view_) ([NSStringFromClass([[_view_ superview] class]) isEqualToString:#"_UIModalItemAlertContentView"])
if(YourMacroName){
//do something
}
Is this what you want?

IOS: hide keyboard on touch UITableView

I am new in iOS development. I want to hide the keyboard when tapping outside of a UITextView.
My TextView is in a cell from an UITableView. The problem is that I have a Toolbar at the top and my buttons doesn't react anymore. I implemented the method "shouldReceiveTouch" but my test is not correct i think. Any ideas? Thank you and sorry for my bad english..
In my ViewDidLoad:
tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
tap.delegate = self;
[self.view addGestureRecognizer:tap];
note: tap is an UITapGestureRecognizer property.
Implemented methods:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIBarButtonItem class]]) {
return NO;
}
return YES;
}
-(void)dismissKeyboard {
[tview resignFirstResponder];
}
UIBarButtonItem is not a subclass of UIView, hence the shouldReceiveTouch still return YES.
Try to exclude the whole UIToolbar or just add the tap gesture recognizer in the UITableViewCell when you initialize the cell in cellForRowAtIndexPath.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIToolbar class]]) {
return NO;
}
return YES;
}
You should add your gesture to table view.
tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
tap.delegate = self;
[tblView addGestureRecognizer:tap];
use didScroll method of UIScrollView delegate to resign keyboard.TableView is also subclass of UIScrollView so it should work.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[tview resignFirstResponder];
}
or use this one
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[tview resignFirstResponder];
}
If you still want to use gesture then add gesture to UIView or self.view or superView of tableView
instead of adding it to tableView
Try following code :----
Keep you code as it is and add this method
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[tview resignFirstResponder];
}
in viewDidLoad set self.view.userInteractionEnabled = yes;
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch view] == tview) {
[tview resignFirstResponder];
}
}

Swipe gestures in Multiview App

I am quite new to iOS development and trying hard to develop an App. I am unable to use swipe gestures in a multiview app. I am pasting the code, can you guys please point out the error.
It's a view based application.
Here is mainViewController.h
#import <UIKit/UIKit.h>
#interface mainViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSArray *listData;
}
#property (nonatomic, retain) NSArray *listData;
#end
Now mainViewController.m
#import "mainViewController.h"
#implementation mainViewController
#synthesize listData;
- (void)viewDidLoad {
NSArray *array =[[NSArray alloc] initWithObjects:#"Apple",#"Boy",#"Cat", nil];
self.listData = array;
[array release];
[super viewDidLoad];
}
- (void)dealloc
{
[listData release];
[super dealloc];
}
#pragma mark - View lifecycle
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return [self.listData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
SimpleTableIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
//cell.textLabel.font = [UIFont boldSystemFontOfSize:50];
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSString *rowValue = [listData objectAtIndex:row];
if([rowValue isEqualToString:#"Apple"])
{
cell.backgroundColor = [UIColor redColor];
}
else
if([rowValue isEqualToString:#"Boy"])
cell.backgroundColor= [UIColor yellowColor];
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSString *rowValue = [listData objectAtIndex:row];
if([rowValue isEqualToString:#"Apple"])
{
mainViewController* flashView=[[mainViewController alloc] initWithNibName:#"fl" bundle:[NSBundle mainBundle]];
[self.view addSubview:flashView.view];
}
//[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.listData=nil;
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 110;
}
#end
I have added an UIViewSubController class with the xib file named "fl".
In fl.h:
#define kMinimumLength 5
#define kMaxVariance 1
#import <UIKit/UIKit.h>
#import "mainViewController.h"
#protocol flDelegate;
#interface fl : UIViewController <UIGestureRecognizerDelegate>
{
CGPoint gestureStartPoint;
id <flDelegate> delegate;
}
#property CGPoint gestureStartPoint;
#property (nonatomic,retain) id <flDelegate> delegate;
#end
#protocol flDelegate
-(IBAction)flDidFinish:(fl *)controller;
#end
And now in fl.m:
#import "fl.h"
#implementation fl
#synthesize delegate;
#synthesize gestureStartPoint;
- (void)dealloc
{
[super dealloc];
}
#pragma mark - View lifecycle
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch =[touches anyObject];
gestureStartPoint =[touch locationInView:self.view];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch =[touches anyObject];
CGPoint CurrentPosition =[touch locationInView:self.view];
if(CurrentPosition.x >= kMinimumLength)
{
NSLog(#"Go");
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
Here everything is working, but it is not detecting swipes, and not printing Go.
I also suggest taking a look at UISwipeGestureRecognizer, but if you prefer staying with your current design, this is the code that I am using elsewhere to detect swipes and pinch (zoom).
You will need to adapt it to your case (you have three methods instead of three branches).
if (touch.phase == UITouchPhaseBegan) {
// NSLog(#"TOUCH BEGAN");
_initialView = touchView;
startTouchPosition1 = [touch locationInView:self];
startTouchTime = touch.timestamp;
if ([allTouches count] > 1) {
startTouchPosition2 = [[[allTouches allObjects] objectAtIndex:1] locationInView:self];
previousTouchPosition1 = startTouchPosition1;
previousTouchPosition2 = startTouchPosition2;
}
}
if (touch.phase == UITouchPhaseMoved) {
// NSLog(#"TOUCH MOVED");
if ([allTouches count] > 1) {
CGPoint currentTouchPosition1 = [[[allTouches allObjects] objectAtIndex:0] locationInView:self];
CGPoint currentTouchPosition2 = [[[allTouches allObjects] objectAtIndex:1] locationInView:self];
CGFloat currentFingerDistance = CGPointDist(currentTouchPosition1, currentTouchPosition2);
CGFloat previousFingerDistance = CGPointDist(previousTouchPosition1, previousTouchPosition2);
if (fabs(currentFingerDistance - previousFingerDistance) > ZOOM_DRAG_MIN) {
NSNumber* movedDistance = [NSNumber numberWithFloat:currentFingerDistance - previousFingerDistance];
if (currentFingerDistance > previousFingerDistance) {
NSLog(#"zoom in");
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_ZOOM_IN object:movedDistance];
} else {
NSLog(#"zoom out");
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_ZOOM_OUT object:movedDistance];
}
}
}
}
if (touch.phase == UITouchPhaseEnded) {
CGPoint currentTouchPosition = [touch locationInView:self];
// Check if it's a swipe
if (fabsf(startTouchPosition1.x - currentTouchPosition.x) >= SWIPE_DRAG_HORIZ_MIN &&
// fabsf(startTouchPosition1.y - currentTouchPosition.y) <= SWIPE_DRAG_VERT_MAX &&
fabsf(startTouchPosition1.x - currentTouchPosition.x) > fabsf(startTouchPosition1.y - currentTouchPosition.y) &&
touch.timestamp - startTouchTime < 0.7
) {
// It appears to be a swipe.
if (startTouchPosition1.x < currentTouchPosition.x) {
NSLog(#"swipe right");
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_SWIPE_RIGHT object:touch];
} else {
NSLog(#"swipe left");
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_SWIPE_LEFT object:touch];
}
}
startTouchPosition1 = CGPointMake(-1, -1);
_initialView = nil;
}
EDIT: about your code...
you are not doing a proper swipe detection. indeed, take this line:
if(CurrentPosition.x >= kMinimumLength)
you are comparing a position (CurrentPosition.x) with a distance (kMinimumLength). This is not really meaningful. What you need saving the last touch position and then calculate the distance between the last touch and the current touch and compare this distance to kMinimumLenght.
The reason why I posted the sample code is that, by inspecting a working implementation you can understand what needs to be done in order to detect a swipe.
You should definitely take a look at UISwipeGestureRecognizers.

Resources