我有一个关于在iPhone上跟踪触摸的快速问题,我似乎无法就此得出结论,因此非常感谢任何建议/想法:
我希望能够跟踪和识别iPhone上的触摸,即。基本上每个触摸都有一个起始位置和一个当前/移动位置。触摸存储在std :: vector中,一旦结束,它们将从容器中删除。他们的位置一旦移动就会更新,但我仍想跟踪他们最初的起点(手势识别)。
我从[event allTouches]获得了接触,事实是,NSSet未排序,我似乎无法识别已经存储在std :: vector中的触摸并引用NSSet中的触摸(所以我知道哪些已经结束,将被移除,或者已被移动等等)
这是我的代码,当然,它只能在触摸屏上只用一根手指完美地工作,但是不止一个,我确实得到了不可预测的结果......
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[self handleTouches:[event allTouches]];
}
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
[self handleTouches:[event allTouches]];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
[self handleTouches:[event allTouches]];
}
- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
[self handleTouches:[event allTouches]];
}
- (void) handleTouches:(NSSet*)allTouches
{
for(int i = 0; i < (int)[allTouches count]; ++i)
{
UITouch* touch = [[allTouches allObjects] objectAtIndex:i];
NSTimeInterval timestamp = [touch timestamp];
CGPoint currentLocation = [touch locationInView:self];
CGPoint previousLocation = [touch previousLocationInView:self];
if([touch phase] == UITouchPhaseBegan)
{
Finger finger;
finger.start.x = currentLocation.x;
finger.start.y = currentLocation.y;
finger.end = finger.start;
finger.hasMoved = false;
finger.hasEnded = false;
touchScreen->AddFinger(finger);
}
else if([touch phase] == UITouchPhaseEnded || [touch phase] == UITouchPhaseCancelled)
{
Finger& finger = touchScreen->GetFingerHandle(i);
finger.hasEnded = true;
}
else if([touch phase] == UITouchPhaseMoved)
{
Finger& finger = touchScreen->GetFingerHandle(i);
finger.end.x = currentLocation.x;
finger.end.y = currentLocation.y;
finger.hasMoved = true;
}
}
touchScreen->RemoveEnded();
}
谢谢!
答案 0 :(得分:8)
跟踪多个触摸的“正确”方式似乎是UITouch事件的指针值。
您可以在此处的“处理复杂的多点触控序列”部分找到更多详细信息 Apple Developer Documentation
答案 1 :(得分:7)
要修复问题,请删除“handleTouches”方法。你在handleTouches方法中做的第一件事是在touchPhase上切换它,但是已经给你了。如果你接触touchesBegan的触摸,你知道触摸是在UITouchPhaseBegan。通过将四种触摸方法中的触摸汇集到一种方法中,您将失去使用四种委托方法的目的。
在每种方法中,Apple都为您提供了处理当前触摸的不同阶段的机会。
第二件事是您不需要搜索当前触摸的事件,它将作为参数提供给您:触摸。
事件由多组触摸组成。为了方便,您可以获得当前的触摸,即使它也可以在活动中找到。
因此,在touchesBegan中,您开始跟踪触摸。
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
NSString *startPoint = NSStringFromCGPoint([[touches anyObject] locationInView:self]);
NSDictionary * touchData = [NSDictionary dictionaryWithObjectsandKeys: startPoint, @"location", touches, @"touch"]
[startingLocations addObject:touchData];
}
我正在使用一系列字典来保存我的触摸数据。
尝试分离您的代码并将其移动到适当的触摸方法中。对于方向,Apple有几个专注于触摸的示例项目,并向您展示如何设置这些方法。
请记住,在每个阶段中,每次触摸都会自动调用这些方法,您无需循环查看事件以了解发生的情况。
指向每组触摸的指针保持不变,只是数据发生变化。
另外,我会阅读关于事件处理的iPhone OS编程指南部分,该部分更深入地介绍了我上面所说的几个图表,解释了触摸与事件之间的关系。
摘录:
在iPhone OS中,一个UITouch对象 表示触摸和UIEvent object代表一个事件。一个事件 对象包含所有触摸对象 目前的多点触控序列和 可以提供特定的触摸对象 视图或窗口(见图3-2)。一个 触摸对象对于给定的持久性 在序列中的手指和UIKit 在跟踪手指时改变它 贯穿始终。触摸属性 这种变化是阶段性的 触摸,它在一个视图中的位置,它 以前的位置及其时间戳。 事件处理代码评估这些 用于确定如何响应的属性 参加活动。
答案 2 :(得分:0)
您应该能够通过存储所有触摸的先前位置来正确整理您的触摸,然后在检测到新触摸时比较这些先前的位置。
在-handleTouches
方法中,您可以在for循环中输入类似的内容:
// ..existing code..
CGPoint previousLocation = [touch previousLocationInView:self];
// Loop through previous touches
for (int j = 0; j < [previousTouchLocationArray count]; j++) {
if (previousLocation == [previousTouchLocationArray objectAtIndex:j]) {
// Current touch matches - retrieve from finger handle j and update position
}
}
// If touch was not found, create a new Finger and associated entry
显然,您需要做一些工作才能将其集成到您的代码中,但我非常确定您可以使用这个想法在屏幕上移动时正确识别触摸。另外我只是意识到CGPoint不能很好地适应NSArray - 你需要将它们包装在NSValue对象中(或者使用不同类型的数组)。