iOS Pinch Scale和Two Finger同时旋转

spe*_*tak 26 iphone cocoa-touch objective-c ipad ios

这是我的代码:

viewDidLoad中:

UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
[self.canvas addGestureRecognizer:pinch];
pinch.delegate = self;

UIRotationGestureRecognizer *twoFingersRotate = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(pinchRotate:)];
[[self canvas] addGestureRecognizer:twoFingersRotate];

twoFingersRotate.delegate = self;
Run Code Online (Sandbox Code Playgroud)

捏和旋转代码:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

-(void)pinchRotate:(UIRotationGestureRecognizer*)rotate
{
    SMImage *selectedImage = [DataCenter sharedDataCenter].selectedImage;

    switch (rotate.state) 
    {
        case UIGestureRecognizerStateBegan:
        {
            selectedImage.referenceTransform = selectedImage.transform;
            break;
        }
        case UIGestureRecognizerStateChanged:
        {
            selectedImage.transform = CGAffineTransformRotate(selectedImage.referenceTransform, ([rotate rotation] * 55) * M_PI/180);
            break;
        }

        default:
            break;
    }
}

-(void)pinch:(UIPinchGestureRecognizer*)pinch
{
    SMImage *selectedImage = [DataCenter sharedDataCenter].selectedImage;
    [self itemSelected];

    switch (pinch.state) 
    {
        case UIGestureRecognizerStateBegan:
        {
            selectedImage.referenceTransform = selectedImage.transform;
            break;
        }
        case UIGestureRecognizerStateChanged:
        {
            CGAffineTransform transform = CGAffineTransformScale(selectedImage.referenceTransform, pinch.scale, pinch.scale);
            selectedImage.transform = transform;
            break;
        }

        default:
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的轮换本身很好,我的规模本身很好,但他们不会一起工作.一个人总是工作,另一个人不工作.当我实现shouldRecognizeSimultaneouslyWithGestureRecognizer时,两个手势似乎相互对抗并产生不良结果.我错过了什么?(是的,我已经实施<UIGestureRecognizerDelegate>)

rob*_*off 34

每次pinch:调用时,您只需根据捏合识别器的比例计算变换.每次pinchRotate:调用时,您只需根据旋转识别器的旋转计算变换.您永远不会将比例和旋转组合成一个变换.

这是一种方法.给自己一个新的实例变量_activeRecognizers:

NSMutableSet *_activeRecognizers;
Run Code Online (Sandbox Code Playgroud)

初始化viewDidLoad:

_activeRecognizers = [NSMutableSet set];
Run Code Online (Sandbox Code Playgroud)

使用一种方法作为两个识别器的操作:

- (IBAction)handleGesture:(UIGestureRecognizer *)recognizer
{
    SMImage *selectedImage = [DataCenter sharedDataCenter].selectedImage;

    switch (recognizer.state) {
        case UIGestureRecognizerStateBegan:
            if (_activeRecognizers.count == 0)
                selectedImage.referenceTransform = selectedImage.transform;
            [_activeRecognizers addObject:recognizer];
            break;

        case UIGestureRecognizerStateEnded:
            selectedImage.referenceTransform = [self applyRecognizer:recognizer toTransform:selectedImage.referenceTransform];
            [_activeRecognizers removeObject:recognizer];
            break;

        case UIGestureRecognizerStateChanged: {
            CGAffineTransform transform = selectedImage.referenceTransform;
            for (UIGestureRecognizer *recognizer in _activeRecognizers)
                transform = [self applyRecognizer:recognizer toTransform:transform];
            selectedImage.transform = transform;
            break;
        }

        default:
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

你需要这个辅助方法:

- (CGAffineTransform)applyRecognizer:(UIGestureRecognizer *)recognizer toTransform:(CGAffineTransform)transform
{
    if ([recognizer respondsToSelector:@selector(rotation)])
        return CGAffineTransformRotate(transform, [(UIRotationGestureRecognizer *)recognizer rotation]);
    else if ([recognizer respondsToSelector:@selector(scale)]) {
        CGFloat scale = [(UIPinchGestureRecognizer *)recognizer scale];
        return CGAffineTransformScale(transform, scale, scale);
    }
    else
        return transform;
}
Run Code Online (Sandbox Code Playgroud)

如果你只是允许旋转和缩放,这是有效的.(我甚至测试过它!)

如果要添加平移,请使用单独的操作方法并进行调整selectedImage.center.尝试使用旋转和缩放使用进行平移selectedImage.transform要复杂得多.


Sri*_*aju 8

为此,您需要实现手势委托shouldRecognizeSimultaneouslyWithGestureRecognizer并同时放置您想要识别的手势.

// ensure that the pinch and rotate gesture recognizers on a particular view can all recognize simultaneously
// prevent other gesture recognizers from recognizing simultaneously
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    // if the gesture recognizers's view isn't one of our views, don't allow simultaneous recognition
    if (gestureRecognizer.view != firstView && gestureRecognizer.view != secondView)
        return NO;

    // if the gesture recognizers are on different views, don't allow simultaneous recognition
    if (gestureRecognizer.view != otherGestureRecognizer.view)
        return NO;

    // if either of the gesture recognizers is the long press, don't allow simultaneous recognition
    if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] || [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
        return NO;

    return YES;
}
Run Code Online (Sandbox Code Playgroud)

此代码需要修改为您想要同时手势识别器的视图.以上代码是您所需要的.


Mik*_*hov 7

Swift 3带平移,旋转和捏合

// MARK: - Gesturies

    func transformUsingRecognizer(_ recognizer: UIGestureRecognizer, transform: CGAffineTransform) -> CGAffineTransform {

        if let rotateRecognizer = recognizer as? UIRotationGestureRecognizer {
            return transform.rotated(by: rotateRecognizer.rotation)
        }

        if let pinchRecognizer = recognizer as? UIPinchGestureRecognizer {
            let scale = pinchRecognizer.scale
            return transform.scaledBy(x: scale, y: scale)
        }

        if let panRecognizer = recognizer as? UIPanGestureRecognizer {
            let deltaX = panRecognizer.translation(in: imageView).x
            let deltaY = panRecognizer.translation(in: imageView).y
            return transform.translatedBy(x: deltaX, y: deltaY)
        }

        return transform
    }

    var initialTransform: CGAffineTransform?

    var gestures = Set<UIGestureRecognizer>(minimumCapacity: 3)

    @IBAction func processTransform(_ sender: Any) {

        let gesture = sender as! UIGestureRecognizer

        switch gesture.state {

        case .began:
            if gestures.count == 0 {
                initialTransform = imageView.transform
            }
            gestures.insert(gesture)

        case .changed:
            if var initial = initialTransform {
                gestures.forEach({ (gesture) in
                    initial = transformUsingRecognizer(gesture, transform: initial)
                })
                imageView.transform = initial
            }

        case .ended:
            gestures.remove(gesture)

        default:
            break
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        return true
    }
Run Code Online (Sandbox Code Playgroud)