首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >旋钮旋转手势识别器

旋钮旋转手势识别器
EN

Stack Overflow用户
提问于 2013-10-29 15:43:11
回答 3查看 541关注 0票数 3

我试图创建一个手势识别器,能够检测4个手指的旋转(类似于当你旋转一个音量旋钮)。

其主要思想是创建UIRotateGestureRecognizer的子类并重写其方法。在-touchesBegan中,我检测到触摸的次数,如果数量低于4,则手势的状态将失败。

在此之后,我将定位点传递给一种算法,该算法可以找到凸包的直径。如果你想一想,你的手指就是顶点,我只需要找到最大距离的两个顶点。得到这两点,我把它们称为伊瓦尔,并把它们传递给超类,因为这是一个简单的旋转,只用两个手指。

这不管用:

  1. 对触摸的检测似乎相当困难。
  2. 很少有-touchesHasMoved被称为
  3. 当它叫它时,它挂起的时间最多。

有人能帮我吗?

以下是代码:

代码语言:javascript
复制
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touches.count<4) {
        //FAIL
        self.state = UIGestureRecognizerStateFailed;
        return;
    }

    //Find the diameter of the convex hull
    NSArray * touchesArray = [touches allObjects];
    NSMutableArray * pointsArray = @[].mutableCopy;
    for (UITouch * touch in touchesArray) {
        [pointsArray addObject:[NSValue valueWithCGPoint:[touch locationInView:touch.view]]];
    }
    DiameterType convexHullDiameter = getDiameterFromPoints(pointsArray);
    CGPoint firstPoint =  convexHullDiameter.firstPoint;
    CGPoint secondPoint = convexHullDiameter.secondPoint;
    for (UITouch * touch in touchesArray) {
        if (CGPointEqualToPoint([touch locationInView:touch.view], firstPoint) ) {
            self.fistTouch = touch;
        }
        else if (CGPointEqualToPoint([touch locationInView:touch.view], secondPoint)){
            self.secondTouch = touch;
        }
    }
    //Calculating the rotation center as a mid point between the diameter vertices
    CGPoint rotationCenter = (CGPoint) {
        .x = (convexHullDiameter.firstPoint.x + convexHullDiameter.secondPoint.x)/2,
        .y = (convexHullDiameter.firstPoint.y + convexHullDiameter.secondPoint.y)/2
    };
    self.rotationCenter = rotationCenter;
    //Passing touches to super as a fake rotation gesture
    NSSet * touchesSet = [[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil];
    [super touchesBegan:touchesSet withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    if (touches.count<4) {
        self.state = UIGestureRecognizerStateFailed;
        return;
    }

    [super touchesMoved:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
}

- (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event  {
    [super touchesCancelled:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event  {
    [super touchesEnded:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-12-02 06:02:01

最初检测困难的原因是,所有的接触可能都不是同时开始的。touchesBegan可能会被多次调用,因为屏幕上会有单独的触摸。您可以使用事件参数查询使用event.allTouches进行的所有当前操作。因此,您当前触发失败手势的方法将不起作用。如果touches.count是<4时,则不应该将状态设置为fail,而应该只返回event.allTouches.count <4时。如果第四次触摸在第一次触摸后的特定时间内没有发生,则可以使用计时器将状态设置为失败。

touchesMoved可能有问题,因为事件对象中的触点与传递给超级程序的集合中的触点不匹配。

票数 2
EN

Stack Overflow用户

发布于 2013-11-26 20:14:18

如果你想一想,你的手指就是顶点,我只需要找到最大距离的两个顶点。

我认为这在实践中是行不通的,即使你能够欺骗UIGestureRecognizer

这就是我如何以‘正确’的方式实现算法:

  1. 记住“老”的感觉。
  2. 当你得到“新”触摸时,试着将每个手指与之前的触摸相匹配。如果你做不到,就失败。
  3. 计算“新”+“旧”触点的中心。
  4. 对于两步前识别出的四个手指,计算以弧度为单位的角度,近似为 new(i) - old(i) divided by distance to center
  5. 如果任何角度太大(> 0.5),则失败。
  6. 这保证了近似是有效的。
  7. 现在计算四个角度的平均值。

恭喜您,您现在有了旋转角(以弧度度量)。

票数 1
EN

Stack Overflow用户

发布于 2013-11-26 14:11:32

如果我有足够的代表,我会把这个写在评论里。

代码语言:javascript
复制
[super touchesMoved:[[NSSet alloc] initWithObjects:self.fistTouch, self.secondTouch, nil] withEvent:event];

您使用的是名为fistTouch的东西,听起来不像您想要的。我猜你想要firstTouch

此外,手势之间可能会发生冲突,而这些手势之间的冲突可能会压倒彼此。你知道iOS7中有一个四指变焦,这是一个全系统的手势吗?另外,应用程序中的4指变焦会关闭它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19662900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档