UIPinchGestureRecognizer позиционирует сжатый вид между двумя пальцами - PullRequest
39 голосов
/ 09 февраля 2011

Я успешно реализовал масштабирование просмотра. Тем не менее, вид не позиционирует себя там, где я хотел. Для стековых потоков с iPad я бы хотел, чтобы мой вид был в центре, как на iPad Photos.app: когда вы сжимаете и масштабируете альбом, фотографии представляются в виде, который расширяется. Это представление приблизительно по центру с верхним правым углом на первом пальце и нижним левым пальцем на другом пальце. Я смешал его с распознавателем панорамирования, но таким образом пользователь всегда должен ущипнуть, а затем панорамировать, чтобы отрегулировать.

Вот такое графическое объяснение, я мог бы опубликовать видео своего приложения, если неясно (не секрет, я пытаюсь воспроизвести Photos.app на iPad ...)

Итак, для начальной позиции пальцев, начиная с масштабирования:

enter image description here

Это фактический «увеличенный» кадр на данный момент. Квадрат больше, но позиция ниже пальцев

given the start position

Вот что я хотел бы иметь: тот же размер, но разные origin.x и y:

enter image description here

(извините за мои плохие навыки фотошопа ^^)

Ответы [ 2 ]

42 голосов
/ 08 марта 2011

Вы можете получить CGPoint средней точки между двумя пальцами с помощью следующего кода в методе 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];
}
11 голосов
/ 10 февраля 2011

Взгляните на пример проекта 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];
    }
}
...