8052
`Line`で画像を見るときのような、ピンチイン後に画像の表示領域を指で動かせるような画面を作っているのですが、どうすればいいか分からず困っています。`ScrollView`をベースにピンチイン・アウトは作ったのですが、ピンチイン後に画像の表示領域が動かせません。どのようにすればピンチイン後に画像の表示領域を動かすことができるでしょうか？どなたか分かる方がいれば教えていただきたいです。すみませんが、よろしくお願いします。

---追記---

`UIPanGestureRecognizer`を使うことでピンチイン後に画像の表示領域を動かすことができたのですが、画像を動かした後にピンチアウトすると、全ての`View`の位置がずれてしまいます。  
例えばピンチインしたい`ImageView`が画面の真ん中にあったとして、ピンチイン後に`UIPanGestureRecognizer`でその拡大された`ImageView`を動かした後ピンチアウトすると、`ImageView`が画面の真ん中に戻るのではなく、画面の右上だったり左下だったりします。  
どうすれば元の位置にピンチアウト後画像を戻すことができるでしょうか？下記にコードを記します。すみませんが、よろしくお願いします。

ViewContoller.h

```

    @interface ViewController : UIViewController<UIScrollViewDelegate>
    
    @property (weak, nonatomic) IBOutlet UIImageView *imageButtonView;
    @property (weak, nonatomic) IBOutlet UIImageView *cancelButton;
    
    @end
    
```

ViewController.m

```

    @implementation ViewController {
        UIPinchGestureRecognizer *pinchGestureRecognizer;
        UIPanGestureRecognizer *panGestureRecognizer;
    }
    
    bool isImageMax = false;
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        _imageButtonView.tag = 100;
        _imageButtonView.userInteractionEnabled = YES;
        _imageButtonView.multipleTouchEnabled = YES;
        _imageButtonView.image = [UIImage imageNamed:@"coupon.png"];
    
        _cancelButton.tag = 200;
        _cancelButton.userInteractionEnabled = YES;
        _cancelButton.hidden = YES;
    
        pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget: self action: @selector(pinchGesture:)];
        panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(viewDragged:)];
    }
    
    - (void)didReceiveMemoryWarning {
    
        [super didReceiveMemoryWarning];
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [[event allTouches] anyObject];
    
        if (touch.view.tag == _imageButtonView.tag) {
            self.view.backgroundColor = [UIColor blackColor];
            _imageButtonView.userInteractionEnabled = NO;
    
            [self imageMoveAndScale:1.0 scaleTo:2.0 moveFrom:_imageButtonView.layer.position moveTo:CGPointMake(self.view.center.x, self.view.center.y) duration:0.5];
    
        } else if (touch.view.tag == _cancelButton.tag) {
    
            [self imageMoveAndScale:2.0 scaleTo:1.0 moveFrom:CGPointMake(self.view.center.x, self.view.center.y) moveTo:_imageButtonView.layer.position duration:0];
        }
    }
    
    - (void)imageMoveAndScale:(float)scaleFrom scaleTo:(float)scaleTo moveFrom:(CGPoint)moveFrom moveTo:(CGPoint)moveTo duration:(float)duration {
        CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
        scaleAnimation.fromValue = [NSNumber numberWithFloat:scaleFrom];
        scaleAnimation.toValue = [NSNumber numberWithFloat:scaleTo];
    
        CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
        moveAnimation.duration = duration;
        moveAnimation.repeatCount = 1;
        moveAnimation.fromValue = [NSValue valueWithCGPoint:moveFrom];
        moveAnimation.toValue = [NSValue valueWithCGPoint:moveTo];
    
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.duration = duration;
        group.repeatCount = 1;
        group.delegate = self;
        group.removedOnCompletion = NO;
        group.fillMode = kCAFillModeForwards;
        group.animations = [NSArray arrayWithObjects:scaleAnimation, moveAnimation, nil];
        [_imageButtonView.layer addAnimation:group forKey:@"move-scale-layer"];
    }
    
    - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
        return _imageButtonView;
    }
    
    
    - (CGFloat)distanceWithPointA:(CGPoint)pointA pointB:(CGPoint)pointB
    {
        CGFloat dx = fabs( pointB.x - pointA.x );
        CGFloat dy = fabs( pointB.y - pointA.y );
        return sqrt(dx * dx + dy * dy);
    }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        if (isImageMax) {
            self.view.backgroundColor = [UIColor whiteColor];
            _cancelButton.hidden = YES;
            _imageButtonView.userInteractionEnabled = YES;
            isImageMax = false;
    
            [self.view removeGestureRecognizer:pinchGestureRecognizer];
            [self.view removeGestureRecognizer:panGestureRecognizer];
    
        } else {
            _cancelButton.hidden = NO;
            isImageMax = true;
    
            [self.view addGestureRecognizer: pinchGestureRecognizer];
        }
    }
    
    - (void)pinchGesture: (UIPinchGestureRecognizer *)gesture {
        if (gesture.scale > 1) {
    
            if (gesture.state == UIGestureRecognizerStateBegan) {
                CGFloat length = 300.0;
    
                [UIView animateWithDuration: 0.5 delay: 0.0 usingSpringWithDamping: 0.4 initialSpringVelocity: 0.8 options: UIViewAnimationOptionCurveEaseIn animations: ^{
                    CGRect viewRect = _imageButtonView.frame;
                    _imageButtonView.frame = CGRectMake(viewRect.origin.x + (viewRect.size.width - length) / 2.0, viewRect.origin.y + (viewRect.size.height - length) / 2.0, length, length);
                } completion: NULL];
    
                [self.view addGestureRecognizer:panGestureRecognizer];
                _cancelButton.hidden = YES;
            }
    
        } else {
            CGFloat length = 160.0;
    
            [UIView animateWithDuration: 0.5 delay: 0.0 usingSpringWithDamping: 0.4 initialSpringVelocity: 0.8 options: UIViewAnimationOptionCurveEaseIn animations: ^{
                CGRect viewRect = _imageButtonView.frame;
                _imageButtonView.frame = CGRectMake(viewRect.origin.x + (viewRect.size.width - length) / 2.0, viewRect.origin.y + (viewRect.size.height - length) / 2.0, length, length);
            } completion: NULL];
    
            [self.view removeGestureRecognizer:panGestureRecognizer];
            _cancelButton.hidden = NO;
        }
    }
    
    - (void)viewDragged:(UIPanGestureRecognizer *)recognizer
    {
        UIGestureRecognizerState state = [recognizer state];
    
        if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged) {
            CGPoint translation = [recognizer translationInView:recognizer.view];
            [recognizer.view setTransform:CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y)];
            [recognizer setTranslation:CGPointZero inView:recognizer.view];
        }
    }
    
    @end
    
```
CC BY-SA 3.0
2015-03-17T04:11:37.100
8002
2015-03-18T06:55:17.270
2015-03-18T02:36:27.493
5210
5210
question
objective-c pinchin
ピンチイン後に画像の表示領域を動かす
画像を動かした後全てのViewの位置がずれてしまうのは、以下のコードが原因と思われます。

```

    - (void)viewDragged:(UIPanGestureRecognizer *)recognizer
    {
        UIGestureRecognizerState state = [recognizer state];
    
        if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged) {
    
            // 修正前の実装
    //      CGPoint translation = [recognizer translationInView:recognizer.view];
    //      [recognizer.view setTransform:CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y)];
    //      [recognizer setTranslation:CGPointZero inView:recognizer.view];
    
            // imageButtonViewだけを動かすように修正
            CGPoint translation = [recognizer translationInView:_imageButtonView];
            [_imageButtonView setTransform:CGAffineTransformTranslate(_imageButtonView.transform, translation.x, translation.y)];
            [recognizer setTranslation:CGPointZero inView:_imageButtonView];
        }
    }
    
```

元々の実装では`[recognizer.view
setTransform...]`でtransformを変更していますが、この時、recognizer.viewがViewControllerのviewを指しているため、結果として、ViewControllerに所属している全てのViewの位置が移動することになっています。

ここでimageButtonViewをちゃんと動かすようにすれば、全てのViewの位置がずれてしまうのは避けられますが・・・
この実装だと、AutoLayoutへの対応などいろいろと面倒なことが出てきそうな気がします。
CC BY-SA 3.0
2015-03-18T06:48:32.730
8052
2015-03-18T06:55:17.270
2015-03-18T06:55:17.270
7459
7459
8002
answer