On 28/06/2012, at 5:31 PM, Quincey Morris wrote:
> On Jun 28, 2012, at 00:14 , Graham Cox wrote:
>
>> Specifically, the problem is that the -clickCount property of an NSEvent is
>> only applicable to mouse events, not touch events. So what's the right way
>> to trap this specific gesture? I have read the various touch-input
>> documentation but nothing became obvious.
>
> The 10.6 document seems to imply that tapping isn't a gesture, so I'd assume
> you'd have to implement the NSResponder methods 'touches…WithEvent:' and use
> the event times to decide (a) if precisely 2 touches begin/end more or less
> simultaneously and (b) if a second 2-touch tap begins within a time interval
> after the 1st one [iOS defaults to 0.5 sec for this interval. Perhaps on the
> Mac you'd use something conditioned by the double-click time instead. I
> dunno.] and (c) if both 2-touch taps last less than some time interval
> [otherwise they'd represent a long press].
>
> Something like that?
>
>
OK, that's pretty much what I'm doing, but it doesn't work all that well yet.
The gesture is recognised, but only sometimes, so the effect for the user is
that the gesture response is flaky.
I'm not sure what I need to do to improve this.
I've written a system somewhat similar (but simpler) than the iOS gesture
recognizer system, where each gesture is recognized by an object, and as soon
as it recognizes the gesture, it informs its delegate and tells the other
recognizers in the set to fugeddaboudit. But in fact, I only have the one
recognizer in there.
Here's the code, which happens to be in my recognizer object, but this can be
thought of as being implemented by a view:
- (void) touchesBeganWithEvent:(NSEvent*) event
{
NSSet* touches = [event touchesMatchingPhase:NSTouchPhaseBegan
inView:self.view];
if([touches count] == 2 )
{
if( self.state == DKWaitingForTap )
{
mFirstTapTime = [NSDate timeIntervalSinceReferenceDate];
[NSTimer scheduledTimerWithTimeInterval:[NSEvent
doubleClickInterval] + 0.1 target:self selector:@selector(timeOut:)
userInfo:nil repeats:NO];
self.state = DKGotFirstTap;
}
else if( self.state == DKGotFirstTap )
{
NSTimeInterval dt = [NSDate
timeIntervalSinceReferenceDate] - mFirstTapTime;
if( dt <= [NSEvent doubleClickInterval])
{
self.state = DKGotSecondTap;
[self notifyDelegate]; // will
eventually call -reset which puts the state back if timer or ended event
doesn't do it first
}
}
}
}
- (void) touchesEndedWithEvent:(NSEvent *)event
{
if( self.state != DKWaitingForTap )
{
NSTimeInterval dt = [NSDate timeIntervalSinceReferenceDate] -
mFirstTapTime;
if( dt > [NSEvent doubleClickInterval])
[self reset];
}
}
- (void) touchesMovedWithEvent:(NSEvent*) event
{
[self reset];
}
- (void) touchesCancelledWithEvent:(NSEvent*) event
{
[self reset];
}
- (void) reset
{
self.state = DKWaitingForTap;
}
- (void) timeOut:(NSTimer*) timer;
{
[self reset];
}
As you can see, I don't bother to track the touches - I only determine that
there are two, and use a simple state machine to detect a double-tap. On the
second tap the touches will be new objects anyway, so there isn't any mileage
in trying to match them up with the touches of the first event. There's also a
timer that resets the state if the second tap is never received.
It works, but since the results are flaky, this is obviously not good enough.
Has anyone actually implemented something like this, and can see where I have
gone wrong?
--Graham
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]