3

4 本の指の回転を検出できるジェスチャ認識機能を作成しようとしています (ボリューム ノブを回転させた場合と同様)。
主なアイデアは、UIRotateGestureRecognizer のサブクラスを作成し、そのメソッドをオーバーライドすることでした。-touchesBeganI detect the number of touch で、数が 4 未満の場合、ジェスチャの状態は失敗です。
その後、凸包の直径を求めるアルゴリズムに位置点を渡します。考えてみると、指が頂点であり、最大距離で 2 つの頂点を見つける必要があります。これら 2 つのポイントを取得したら、ivar として参照し、スーパークラスに渡します。これは、2 本の指だけで簡単に回転できるためです。
それは動作しません:

  1. タッチの検出はかなり難しいようです
  2. -touchesHasMovedと呼ばれることはめったにありません
  3. 呼び出されると、ほとんどの場合ハングします

誰かが私を助けることができますか?

コードは次のとおりです。

- (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];
}
4

3 に答える 3

2

最初の検出が難しい理由は、すべてのタッチが同時に開始されない可能性があるためです。touchesBegan は、別々のタッチが画面に着地するときに複数回呼び出される可能性があります。event パラメータを使用して、event.allTouches で現在のすべてのタッチを照会できます。したがって、ジェスチャを失敗させるための現在のアプローチは機能しません。touches.count が < 4 の場合に状態を失敗するように設定する必要はありませんが、代わりに event.allTouches.count < 4 の場合に戻るだけです。最初。

イベント オブジェクト内のタッチが、スーパーに渡すセット内のタッチと一致しないため、touchesMoved に問題がある可能性があります。

于 2013-12-02T06:02:01.547 に答える