SwipeGesture in Iphone Cocos2d - iphone

I am using UISwipeGestureRecognizer to get swipe gesture in iPhone. i want to get 2 location points on Began of swipe touch and on end of swipe touch. i have implemented swipe touch method as below
- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
CGPoint touchLocation = [recognizer locationInView:recognizer.view];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
CCLOG(#"Hello %# - %d",NSStringFromCGPoint(touchLocation),recognizer.state);
if (recognizer.state == UIGestureRecognizerStateBegan) {
CGPoint touchLocation = [recognizer locationInView:recognizer.view];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
CCLOG(#"UIGestureRecognizerStateBegan %#",NSStringFromCGPoint(touchLocation));
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
CCLOG(#"UIGestureRecognizerStateChanged");
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint touchLocationEnd = [recognizer locationInView:recognizer.view];
touchLocationEnd = [[CCDirector sharedDirector] convertToGL:touchLocationEnd];
touchLocationEnd = [self convertToNodeSpace:touchLocationEnd];
CCLOG(#"UIGestureRecognizerStateEnded %#",NSStringFromCGPoint(touchLocationEnd));
}
//}
}
My swipe touch is working. but it only shows UIGestureRecognizerStateEnded. even when i swipe on screen and my touch is not ended yet but the StateEnded is called. how can i call StateBegin and get location and then StateEnd. right now just StateEnded is working other two Begin and Changing are not working.

Update:
I find the reason:
A swipe is a discrete gesture, and thus the associated action message
is sent only once per gesture.
And this image:
So there are only three states for UISwipeGestureRecognizer:possible, recognized and ended. But I still don't know why possible is not called.
I tried your code and get the same result. I also don't know why this happen. If you can't find solution for this problem I suggest you use the for touch methods to analysis the touch yourself. This can surely handle the event but a little complicated than use gesture recognizer.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

Related

touchesMoved reaching out of my view bounds

I have subclassed UIView and there initially my view will be in a default color and i need to fill some different color on touch (from x axis = 0 to user touched point),here the problem is touchesMoved even if i drag out of my self view bounds it is getting those points,how to restrict it to only for my self view bounds.
I googled & tried below snippets but of no luck
if([self pointInside:point withEvent:nil]){
[self fillColor];
}
My touchesMoved method is as below,
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
endPoint = point;
NSLog(#"moved x: %f,y: %f",point.x,point.y);
if(CGRectContainsPoint([self frame], endPoint)){ // this also not working
[self fillColor];
}
}
Any help is appreciated in advance.
just set tag in viewDidLoad: method and use bellow logic..
fillColorView.tag = 111;
and use bellow logic in touchesMoved: method like bellow..
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *tap = [touches anyObject];
CGPoint pointToMove = [tap locationInView:fillColorView];
if([tap.view isKindOfClass:[UIView class]])
{
UIView *tempView=(UIView *) tap.view;
if (tempView.tag == 111){
[self fillColor];
}
}
}
hope this help you...
In your touchesMoved method, CGPoint point = [touch locationInView:self]; replcae self by the view in which you wants the touch to be worked.
self will get the complete view, you should pass your drawingView at there, so that it will detetc touch only on that view.

Gesture detection on ios 3.1.3

In ios 3.1 and above how I can detect the Gesture in an UIView...
In ios >= 3.2.3 I use this code...(for example):
UISwipeGestureRecognizer *oneFingerSwipeLeft =
[[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerSwipeLeft:)] autorelease];
[oneFingerSwipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[[self view] addGestureRecognizer:oneFingerSwipeLeft];
UISwipeGestureRecognizer *oneFingerSwipeRight =
[[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerSwipeRight:)] autorelease];
[oneFingerSwipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[[self view] addGestureRecognizer:oneFingerSwipeRight];
Someone have an idea/example...
Thanks
You're going to have to subclass the UIView (or implement the stuff within the view controller if the layout isn't too complicated) and track the gestures you want for yourself using ye olde UIResponder methods touchesBegan:withEvent:, etc.
For example:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(!trackingTouch && [touches count] == 1)
{
trackingTouch = [touches anyObject];
startingPoint = [trackingTouch locationInView:relevantView];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(trackingTouch && [touches containsObject:trackingTouch])
{
CGPoint endingPoint = [trackingTouch locationInView:relevantView];
trackingTouch = nil;
if(endingPoint.x < startingPoint.x)
NSLog(#"swipe left");
else
NSLog(#"swipe right");
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
// don't really care about touchesMoved:withEvent:
That's an imperfect solution because it assumes that all finger down to finger up progressions are necessarily swipes. You'll probably want to implement some sort of maximum time duration or track velocities in touchesMoved:withEvent: or check that the touch moved at least a minimum distance. I think it's because people were making different decisions for all of those sorts of things that Apple ended up providing the UIGestureRecognizers.

Pass on a Tap to an UITextView

I was wondering how to pass on a tap on an UIView to an UITextView. This is my code so far:
- (void)foundTap:(UITapGestureRecognizer *)recognizer {
label.text = #"Touch detected";
[self.view bringSubviewToFront:aTextView];
[aTextView touchesBegan:touches withEvent:event];
}
Now, this obviously does not work as touches and event are not defined. But how do I define them? I can't declare touches as 1 (won't work). I could initialise it like so:
UITouch *touches =[touches anyObject];
But then again, touches is still undeclared. And I have no idea of how to declare the event. This is usually easy if you use the - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {} method, but I want to pass on the tap not the touches. Any help would be very much appreciated.
Edit:
I rewrote the method, but I still can't pass on the tap to the UITextView. I now need to double tap in order to edit it, i.e. the first tap for bringing the aTextView upfront and the second tap will then edit the UITextView (as it is in front and thus receives all the touches swipes etc.):
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.view];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x); // will always be positive
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y); // will always be positive
if (deltaY == 0 && deltaX == 0) {
label.text = #"Touch"; [self performSelector:#selector(eraseText) withObject:nil afterDelay:2];
[self.view bringSubviewToFront:aTextView];
[self.view bringSubviewToFront:doneEdit];
[aTextView touchesBegan:touches withEvent:event];
}
}
See if this previous SO question iPhone: Detecting Tap in MKMapView helps you.

How would I drag UITextView around the view screen?

I have a project where a UITextView (for multilines) can be dragged around the screen. So far my solution to this has been an overlay of an invisible UIButton which when dragged its center is the same as the UITextView's center.
However I've seen apps that seem to just allow the UITextView to be dragged and edited on the fly so it seems there might not be an overlay in those but I'm not sure.
Thoughts?
By the way, c in this code is the UIButton and this is how I have moved it thus far:
- (void) draggedOut: (UIControl *) c withEvent: (UIEvent *) ev
{
if(self.interfaceOrientation == UIInterfaceOrientationPortrait)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
else if(self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
else if(self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
else if(self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
c.center = [[[ev allTouches] anyObject] locationInView:self.view];
AddedText.center = c.center;
}
}
- (void)panTextView:(UIPanGestureRecognizer *)recognizer {
NSLog(#"panning");
location1 = [recognizer translationInView:draggableTextView];
recognizer.view.center = CGPointMake(recognizer.view.center.x + location1.x,
recognizer.view.center.y + location1.y);
[recognizer setTranslation:CGPointMake(0,0) inView:draggableTextView];
location1 =[recognizer locationInView:draggableTextView];
NSLog(#"tranlation %#",NSStringFromCGPoint(location1));
[_imgpic addSubview:recognizer.view];
appDelegate.txt=draggableTextView.text;
}
call this method after creating textview.
Well have not been able to manipulate the actual uitextview.
First tried making a button overlay that could be moved and could be pressed to start editing, but it wasn't centered properly.
Then tried the above method to move the UITextView itself. But it would only work on touches or drags. (Note this was a modified form of touchesBegan & touchesMoved)
Ended up with a UIScrollView with the UITextView as a subview. Now it can move smoothly just that it can be moved from any place on the screen. Not optimal but is the best result to thus keep everything else intact.
Does the textView need to support scrolling? If so, this could get complicated.
But if not, there are two approaches. 1) subclass the textview and override touchesBegan, touchesMoved, touchesEnded. 2) write a gesture recognizer that processes the same messages and attach it to the textview.
Here's an example of a Gesture recognizer that will do the job:
#interface TouchMoveGestureRecognizer : UIGestureRecognizer
{
CGPoint _ptOffset;
}
#end
#implementation TouchMoveGestureRecognizer
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* t = [touches anyObject];
_ptOffset = [t locationInView: self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* t = [touches anyObject];
CGPoint pt = [t locationInView: self.view.superview];
pt.x -= _ptOffset.x;
pt.y -= _ptOffset.y;
CGRect r = self.view.frame;
r.origin = pt;
self.view.frame = r;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
_ptOffset = CGPointMake(-1, -1);
}
#end
and, how to use it:
- (void)viewDidLoad {
[super viewDidLoad];
_textView.scrollEnabled = NO;
TouchMoveGestureRecognizer* gr = [[[TouchMoveGestureRecognizer alloc] init] autorelease];
[_textView addGestureRecognizer: gr];
}

Programmatically pass touches to UIScrollView to scroll

Basically I'm trying to make UIScrollView only scroll on higher angles. As in right now if you move your finger 10 degrees off horizontal, the scrollview will scroll. I'd like to push that up to, say, 30 degrees.
After doing some reading, I established the best way to do this would be to put a subclassed UIView on top of the scrollview. If the UIView on top's touches are above 30 degrees, pass it down to the scrollview, and otherwise don't.
However, I can't figure out how to pass the touches down. Here's my code right now:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"glass touch began");
UITouch *touch = [touches anyObject];
beginning_touch_point = [touch locationInView:nil];
[scroll_view touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"glass touch ended");
UITouch *touch = [touches anyObject];
CGPoint previous_point = beginning_touch_point;
CGPoint current_point = [touch locationInView:nil];
float x_change = fabs(previous_point.x - current_point.x);
float y_change = fabs(previous_point.y - current_point.y);
if(x_change > y_change)
{
if(previous_point.x - current_point.x < 0)
{
[(MyScheduleViewController *)schedule_controller didFlickLeft];
}
else
{
[(MyScheduleViewController *)schedule_controller didFlickRight];
}
[scroll_view touchesCancelled:touches withEvent:event];
}
else
{
[scroll_view touchesEnded:touches withEvent:event];
}
}
I know right now that it's checking for 45 degrees, but that's not the important thing. What is important is that the touches are indeed getting passed down correctly to my scroll_view. I have it doing a NSLog() on touchesbegan and touchesended, and it's doing both correctly. It's just not scrolling. I'm worried touchesBegan and touchesEnded cannot cause a scroll. Does anyone know what can, or what I'm doing wrong?
I also tried to do the same but didn't succeed. It seems scrollView doesn't handle touchesMoved/touchesBegan, but it handles some other events to understand that user wants to scroll the view.
For me the solution was to determine thet shift value and set it explicitly as a scrollView content offset. It looked like this (I don't have the exact source code no, this code may work incorrectly):
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint curr = [touch locationInView: self];
CGPoint offset = [scrollView contentOffset];
[scrollView setContentOffset: CGPointMake(offset.x + (curr.x - prev.x), offset.y) animated:YES];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
prev = [[touches anyObject] previousLocationInView: self];
}