in my app i'm able to detect a touch by connecting the view to an action touch down event. However, i want to be able to detect that the user lifted his finger off screen. am i able to do that?
Edit: sorry for the short post. actually i have no hint how to do that or even to try to do that!
Well, that depends on where you're trying to track the touch removal. If for example, you're using a button and you've already linked an action to touchDown, you can simply link another action for the buttons control event touch up inside/outside.
If you're interested in tracking that touches ended on the entire screen, you can use -touchesEnded: withEvent:.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
}
Related
I'm creating a custom control* by subclassing UIControl and overriding the following methods:
- beginTrackingWithTouch:withEvent:
- continueTrackingWithTouch:withEvent:
- endTrackingWithTouch:withEvent:
- cancelTrackingWithEvent:
This control will support multitouch interaction. Specifically, one or two fingers may touch down, drag for some duration, and then touch up, all independently.
My issue comes at the end of these multitouch events, in endTrackingWithTouch:withEvent:. The system calls this method on my control exactly once per multitouch sequence, and it is called on the first touch up that occurs. This means that the second touch, which could still be dragging, will no longer be tracked.
This sequence of actions serves as an example for this phenomenon:
Finger A touches down. beginTracking is called.
Finger A drags around. continueTracking is called repeatedly to update my control.
Finger B touches down. beginTracking is called.
Fingers A and B drag around. continueTracking is called repeatedly to update my control.
Finger B touches up. endTracking is called.
Finger A drags around. No methods are called.
Finger A touches up. No methods are called.
The issue lies in the final three steps in this sequence. The documentation for UIControl says the following of endTrackingWithTouch:withEvent::
Sent to the control when the last touch for the given event completely ends, telling it to stop tracking.
Yet it seems to me that after finger B touches up in step 5, above, the last touch for the given event has not yet completely ended. That last touch is finger A!
*A range slider, if you must ask. But there are already plenty of open source range sliders, you say. Yes, true, but this one will support multitouch and Auto Layout.
I had the same issue in custom control with multitouch.
Because UIControl is subclass of UIView that inherits from UIResponder, so feel free to use:
- (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;
methods.
These methods work fine in UIControl subclass.
I'm wanting to be able to detect the following in Cocos2d v3:
A touch is initiated and held, then a second touch occurs somewhere else on the screen. Think of holding with one finger, and tapping with a second.
I've tried to use - (void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event but this is only called the first time the second touch occurs, not subsequently.
To be clear, if I hold a touch on the screen and then tap somewhere else, the above method is called. But if I continue holding the first touch and then tap a second time, the above method is not called.
Also, touchBegan: is only called when the first touch occurs (i.e. the initial holding touch) and touchEnded: is only called when all touches are removed, including the initial holding touch.
I'd like to know:
1) How to recognise the above gesture in Cocos2d v3?
2) If 1) isn't possible, would there be a way to do it with my own gesture recogniser, and how would I implement my own gesture recogniser into Cocos2d v3?
Turns out by default Cocos2d V3 only responds to a single touch by default.
The solution:
self.multipleTouchEnabled = TRUE;
This means now every new touch will call:
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
And every time a finger is lifted from the screen it will call:
-(void) touchEnded:(UITouch *)touch withEvent:(UIEvent *)event
Even if there are other touches continuing.
if you use void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) then you get each touch count using pTouches->count();
is there a way to detect second click on a segment in UISegmentedControl? I found:
Detect second click on a segment
however, it is stated that:
If you set a segmented control to have a momentary style, a segment doesn’t show itself as selected (blue background) when the user touches it. The disclosure button is always momentary and doesn’t affect the actual selection.
Is there a way to detect second click as well as trigger the selection action and show the segment as selected?
If there is no straight forward way to do it, what I was thinking, is that I first have the momentary flag set to YES, then upon each click, manually update the selection state, but then I also need to update/deselect other segments.
Thanks
The solution is to have a custom subclass of UISegmentedControl and check it yourself like this.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
current = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
if (current == self.selectedSegmentIndex)
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
I had an other solution all in touchesBegan, but it's not working anymore in iOS 7. There is also other solution on Stack Overflow that are not working in iOS 6 and greater.
To make a particular segment click-able again is not possible, but you can reset the whole segmentControl using UISegmentedControlNoSegment.
[self.segmentCtrlOutlet setSelectedSegmentIndex:UISegmentedControlNoSegment];
what you have to do is put the above code in the place where that code executes when you click on a particular segment of UISegmentedControl.
for eg. In my project when I click on a segment, UIPopoverController opens up and inside it I have UIPicker, so I use the above code in UIPicker delegate method "didSelectRow"
What I want to implement is column matching type functionality. I have three buttons on right column and three on left column with some info on them. I want to draw path from one button on right side to any of the button on left side by dragging finger.
I would use UIBezierPath path to draw path, and for that definitely a start and end point is needed.
Now the issue is how can I trigger touchesBegan, touchesMoved and touchesEnded methods by tapping on buttons so that I can get start and end points.
Another option that I am thinking about is to cover all the buttons with an invisible UIView, and somehow check if the point touched of this overlay view lies in any of the button frames.
BTW I can replace these buttons with simple UIImageView as well. I added buttons just for the sake of getting touch points.
Any help.
Create a subclass of UIButton and add this...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
[self.nextResponder touchesBegan:touches withEvent:event];
}
This will get you your touches within the button.
Uncheck User Interaction Enabled checkbox of UIButton. You will get call for touchesbegan method on that button.
Is there a way to register all touch up through touchesEnded. It will only fire when there is a tap that lasts more than a second or two. Is there away to have it fire on all touch ups? It registers all touchesBegan.
Here is the simple code:
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Touch Ended");
}
-touchesEnded:withEvent: gets called even for brief touches, like taps. You probably have something in your responder chain that's handling the touch. For example, scroll views will normally delay touches until they figure out whether the user is trying to scroll, and gesture recognizers can also delay touch events. Specifically, UIGestureRecognizer has a delaysTouchesEnded property that may be interfering with your code.
Multiple touches are disabled by default. If you want to receive multiple touch events you must set the a multipleTouchEnabled to YES of the view which you use. To do this in your ViewDidLoad just write self.view.multipleTouchEnabled= YES because it's just a property. Another issue may be connected with Magic Trackpad because it adds a delay before it decides that you have ended a touch.Try to disable it : >System Preferences>Personal>Universal Access>Mouse & Trackpad>Trackpad Options>Ignore Trackpad when mouse is present.