web-dev-qa-db-ja.com

UIPinchGestureRecognizerは、2本の指の間に挟まれたビューを配置します

ビューのズームをピンチインすることに成功しました。ただし、ビューが希望どおりの位置に表示されません。 iPadのstackoverflowersの場合、ビューをiPad Photos.appのように中央に配置したいと思います。アルバムをピンチ&ズームすると、写真が拡大するビューに表示されます。このビューは、ほぼ中央に配置されており、最初の指の右上の角と、もう一方の指の左下の指が表示されています。パン認識機能と組み合わせましたが、この方法では、ユーザーは常にピンチしてからパンして調整する必要があります。

ここに非常にグラフィックな説明があります、それが不明確な場合はアプリのビデオを投稿できます(秘密はありません、iPadのPhotos.appを再現しようとしています...)

したがって、指の初期位置について、ズームを開始します。

enter image description here

現在のところ、これは実際の「ズーム」フレームです。四角は大きいですが、位置は指の下です

given the start position

これが私が欲しいものです:同じサイズですが、Origin.xとyは異なります:

enter image description here

(フォトショップのスキルが低いことを申し訳ありません^^)

39
Thomas Joulin

メソッドCGPointの次のコードを使用して、2本の指の間の中点のhandlingPinchGestureを取得できます。

CGPoint point = [sender locationInView:self];

私のhandlePinchGestureメソッド全体を以下に示します。

/*
instance variables

CGFloat lastScale;
CGPoint lastPoint;
*/

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)sender {
    if ([sender numberOfTouches] < 2)
        return;

    if (sender.state == UIGestureRecognizerStateBegan) {
        lastScale = 1.0;
        lastPoint = [sender locationInView:self];
    }

    // Scale
    CGFloat scale = 1.0 - (lastScale - sender.scale);
    [self.layer setAffineTransform:
        CGAffineTransformScale([self.layer affineTransform], 
                               scale, 
                               scale)];
    lastScale = sender.scale;

    // Translate
    CGPoint point = [sender locationInView:self];
    [self.layer setAffineTransform:
        CGAffineTransformTranslate([self.layer affineTransform], 
                                   point.x - lastPoint.x, 
                                   point.y - lastPoint.y)];
    lastPoint = [sender locationInView:self];
}
43
mishimay

Touchesサンプルプロジェクト をご覧ください。具体的には、これらの方法は次のことに役立ちます。

// scale and rotation transforms are applied relative to the layer's anchor point
// this method moves a gesture recognizer's view's anchor point between the user's fingers
- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        UIView *piece = gestureRecognizer.view;
        CGPoint locationInView = [gestureRecognizer locationInView:piece];
        CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];

        piece.layer.anchorPoint = CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
        piece.center = locationInSuperview;
    }
}

// scale the piece by the current scale
// reset the gesture recognizer's rotation to 0 after applying so the next callback is a delta from the current scale
- (void)scalePiece:(UIPinchGestureRecognizer *)gestureRecognizer
{
    [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
        [gestureRecognizer view].transform = CGAffineTransformScale([[gestureRecognizer view] transform], [gestureRecognizer scale], [gestureRecognizer scale]);
        [gestureRecognizer setScale:1];
    }
}
11
Felix