LoginSignup
39
38

More than 5 years have passed since last update.

ビューの拡大と回転のジェスチャを同時に可能にする

Posted at

拡大はUIPinchGestureRecognizer、回転はUIRotationGestureRecognizerを使います。

ポイントは、ビューにUIGestureRecognizerDelegateを実装するようにして、shouldRecognizeSimultaneouslyWithGestureRecognizerで拡大(ピンチ)と回転の同時処理を受け付けるようにする点です。

ビュー宣言
@interface HogeView <UIGestureRecognizerDelegate> {
    CGAffineTransform _currentTransform;
    float _scale;
    float _angle;
    BOOL _isMoving;
}
@end
ジェスチャの同時処理を許可
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

ジェスチャ登録時にはtargetとは別に、delegateを設定する必要があります。

初期化
- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // 回転ジェスチャをビューに登録
        UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGesture:)];
        rotation.delegate = self;
        [self addGestureRecognizer:rotation];

        // ピンチジェスチャをビューに登録
        UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGesture:)];
        pinch.delegate = self;
        [self addGestureRecognizer:pinch];

        _isMoving = NO;
        _scale = 1.0f;
        _angle = 0.0f;
    }
    return self;
}

回転ジェスチャと拡大ジェスチャのハンドラはほぼ同じです。
ジェスチャ実行中の状態(回転角度+拡大率)をフィールドで保持するようにしておき、どちらのジェスチャハンドラでも回転+拡大の両方のアフィン変換を適用します。

回転ジェスチャ
- (void)rotationGesture:(UIRotationGestureRecognizer*)gesture {
    // ジェスチャ開始時
    if (!_isMoving && gesture.state == UIGestureRecognizerStateBegan) {
        _isMoving = YES;
        _currentTransform = self.transform;
    }
    // ジェスチャ終了時
    else if (_isMoving && gesture.state == UIGestureRecognizerStateEnded) {
        _isMoving = NO;
        _scale = 1.0f;
        _angle = 0.0f;
    }

    // 回転角度取得
    _angle = gesture.rotation;

    // アフィン変換を適用
    CGAffineTransform transform = CGAffineTransformConcat(CGAffineTransformConcat(_currentTransform, CGAffineTransformMakeRotation(_angle)), CGAffineTransformMakeScale(_scale, _scale));
    gesture.view.transform = transform;
}
拡大ジェスチャ
- (void)pinchGesture: (UIPinchGestureRecognizer *)gesture {
    // ジェスチャ開始時
    if (!_isMoving && gesture.state == UIGestureRecognizerStateBegan) {
        _isMoving = YES;
        _currentTransform = self.transform;
    }
    // ジェスチャ終了時
    else if (_isMoving && gesture.state == UIGestureRecognizerStateEnded) {
        _isMoving = NO;
        _scale = 1.0f;
        _angle = 0.0f;
    }

    // 拡大率取得
    _scale = gesture.scale;

    // アフィン変換を適用
    CGAffineTransform transform = CGAffineTransformConcat(CGAffineTransformConcat(_currentTransform, CGAffineTransformMakeRotation(_angle)), CGAffineTransformMakeScale(_scale, _scale));
    gesture.view.transform = transform;
}
39
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
38