捏合與拖動手勢實現視圖的縮放拖動 以及 任一邊界拖進屏幕自動回彈

實現這個功能也是被逼無奈,項目需要縮放移動有很多小頁籤的WKWebView,嘗試了UIScrollView,但是很不理想,因爲webview需要側滑和上下滑動,所以縮放拖動絕大部分都無法觸發,只得採用手勢實現。在網上查閱了大量資料,終於實現了該功能,廢話不多說,上代碼:

1、定義縮放倍數和偏移量

// 縮放倍數
#define minScale  1
#define maxScale  2
// 偏移量
#define Offset 0

2、定義需要用到的屬性

@property (nonatomic,strong) UIImageView *imgView;// 要縮放的視圖
// 縮放
@property (nonatomic, assign) CGFloat lastScale;// 上一次縮放的比例
@property (nonatomic, strong) UIPinchGestureRecognizer *pinch;// 捏合手勢
@property (nonatomic, strong) UIPanGestureRecognizer *pan;// 平移手勢

3、初始化視圖、手勢,並設置手勢

    _imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.jpg"]];
    _imgView.frame = self.view.frame;
    _imgView.userInteractionEnabled = YES;
    [self.view addSubview:_imgView];

    _pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchAction:)];
    _pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];

    [_imgView addGestureRecognizer:_pinch];
    [_imgView addGestureRecognizer:_pan];

4、 設置錨點

- (void)adjustAnchorPointForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    //UIGestureRecognizerStateBegan意味着手勢已經被識別
    if (gestureRecognizer.state ==UIGestureRecognizerStateBegan)
    {
        //手勢發生在哪個view上
        UIView *piece = gestureRecognizer.view;
        //獲得當前手勢在view上的位置。
        CGPoint locationInView = [gestureRecognizer locationInView:piece];

        piece.layer.anchorPoint =CGPointMake(locationInView.x / piece.bounds.size.width, locationInView.y / piece.bounds.size.height);
        //根據在view上的位置設置錨點。
        //防止設置完錨點過後,view的位置發生變化,相當於把view的位置重新定位到原來的位置上。
        CGPoint locationInSuperview = [gestureRecognizer locationInView:piece.superview];
        piece.center = locationInSuperview;
    }
}

5、 縮放方法

- (void)pinchAction:(UIPinchGestureRecognizer *)gestureRecognizer{

    UIGestureRecognizerState state = [gestureRecognizer state];

    if(state == UIGestureRecognizerStateBegan) {
        _lastScale = [gestureRecognizer scale];
    }

    if (gestureRecognizer.scale > 1) {
        [self adjustAnchorPointForGestureRecognizer:gestureRecognizer];
    }else{
        _imgView.layer.anchorPoint =CGPointMake(0.5, 0.5);
        _imgView.center = self.view.center;
    }

    CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:@"transform.scale"] floatValue];

    if (state == UIGestureRecognizerStateBegan ||
        state == UIGestureRecognizerStateChanged) {

        CGFloat newScale = 1 -  (_lastScale - [gestureRecognizer scale]);
        newScale = MIN(newScale, maxScale / currentScale);
        newScale = MAX(newScale, minScale / currentScale);
        CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
        NSLog(@"newScale = %f,currentScale = %f",newScale,currentScale);
        [gestureRecognizer view].transform = transform;
        _lastScale = [gestureRecognizer scale];
    }
    if (state == UIGestureRecognizerStateEnded) {
        if (currentScale >= minScale && currentScale <= minScale + 0.1) {
            [_imgView removeGestureRecognizer:_pan];
        }else if(currentScale > minScale + 0.1 && currentScale <= maxScale){
            [_imgView addGestureRecognizer:_pan];
        }
    }
}

6、 拖動方法

- (void)panAction:(UIPanGestureRecognizer *)gestureRecognizer{

    if (gestureRecognizer.state == UIGestureRecognizerStateBegan ||
        gestureRecognizer.state == UIGestureRecognizerStateChanged) {

        if (!(_imgView.frame.origin.x == 0 &&
              _imgView.frame.origin.y == 0 &&
              _imgView.frame.size.width == self.view.frame.size.width &&
              _imgView.frame.size.height == self.view.frame.size.height)) {
            CGPoint translation = [gestureRecognizer translationInView:self.view];
            gestureRecognizer.view.center = CGPointMake(gestureRecognizer.view.center.x + translation.x, gestureRecognizer.view.center.y + translation.y);
            [gestureRecognizer setTranslation:CGPointZero inView:self.view];
        }
    }

    CGRect rect = _imgView.frame;
    if (_imgView.frame.origin.x > 0 + Offset) {//左邊進入屏幕
        NSLog(@"左邊進入屏幕");
        [UIView animateWithDuration:0.25 animations:^{
            CGPoint point = CGPointMake(gestureRecognizer.view.center.x - gestureRecognizer.view.frame.origin.x, gestureRecognizer.view.center.y);
            gestureRecognizer.view.center = point;
        }];
    }else if (CGRectGetMaxX(rect) < self.view.frame.size.width + Offset){
        NSLog(@"右邊進入屏幕");
        [UIView animateWithDuration:0.25 animations:^{
            CGRect newRect = CGRectOffset(_imgView.frame, self.view.frame.size.width - CGRectGetMaxX(_imgView.frame), 0);
            _imgView.frame = newRect;

        }];
    }
    if (_imgView.frame.origin.y > 0 + Offset) {//上邊進入屏幕
        NSLog(@"上邊進入屏幕");
        [UIView animateWithDuration:0.25 animations:^{
            CGPoint point = CGPointMake(gestureRecognizer.view.center.x, gestureRecognizer.view.center.y - gestureRecognizer.view.frame.origin.y);
            gestureRecognizer.view.center = point;
        }];
    }else if(CGRectGetMaxY(rect) < self.view.frame.size.height + Offset){
        NSLog(@"下邊進入屏幕");
        [UIView animateWithDuration:0.25 animations:^{
            CGRect newRect = CGRectOffset(_imgView.frame, 0, self.view.frame.size.height - CGRectGetMaxY(_imgView.frame));
            _imgView.frame = newRect;
        }];
    }

}

手勢實現也是萬不得已才用的,如果有哪位大神解決了UIScrollView縮放有多個側滑頁籤,並且可以上下滑動的WKWebView,請給我留言,相互交流,萬分感謝。

轉載請註明出處,萬分感謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章