4

如果有人遇到适用于 iOS 的谷歌地图应用程序,那么它有一个很棒的功能,可以用一根手指放大/缩小:双击 uiscrollview,然后立即向上或向下滑动手指以放大/缩小。有谁知道这是如何实现的?谷歌有没有发布任何片段?

4

3 回答 3

3

我将此功能添加到我的 UIScrollView 类别中
实际的点击识别很容易,计算“正确”(感觉“正确”)zoomScale是问题......如果您认为该类别处理得不够好,请不要犹豫告诉我并打开一个新问题github页面。

于 2013-07-19T15:11:33.877 回答
2

使用 UIPanGestureRecognizer 跟踪向上/向下拖动。为了确保它只在双击时触发,请给它一个执行以下操作的委托:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if gestureRecognizer == yourZoomRecognizer {
        return touch.tapCount == 2
    } else {
        return true
    }
}

现在处理来自手势识别器的消息。您可以像这样导出缩放比例:

let zoomFactor: CGFloat = 1.01        //Each point of pan zooms in or out by this much
var zoomScale: CGFloat = 1            //Dummy variable for example purposes.

@IBAction func handleZoomGesture(sender: UIPanGestureRecognizer) {
    if sender.state == .began {
        //Set initial translation to reflect the current zoomScale
        let logZoom = log(zoomScale) / log(zoomFactor)
        sender.setTranslation(CGPoint(x: 0, y: logZoom), in: sender.view)
    } else if sender.state == .changed {
        let logZoom = sender.translation(in: sender.view).y
        zoomScale = pow(zoomFactor, logZoom)
    }
}

这并没有显示在滚动视图上实际设置 zoomScale,这是一堆额外的代码 - 您需要获取平移手势的位置并将缩放围绕该位置居中。您还需要钳制缩放比例,并且可能还要处理缩放结束。

于 2017-11-13T18:33:29.293 回答
0

此示例使用 UIScrollView 的常规缩放功能,其中包含 UIImageView 作为子视图。例如,您可以在 MWPhotoBrowser 库中找到这种缩放的实现。_imageView、_doubleTapBeganPoint、_longPressBeganPoint、_minScale 是你的类(UIScrollView 子类)iVars。所以从初始化开始:

UILongPressGestureRecognizer* lpgs = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(imageLongPressed:)];
lpgs.minimumPressDuration = .2;
[self addGestureRecognizer:lpgs];

标准缩放处理程序:

- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return _imageView;
}

使用 touchesBegan 捕捉双击(由于某种原因,UITapGestureRecognizer 不想与 UILongPressGestureRecognizer 一起使用):

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    NSUInteger tapCount = touch.tapCount;
    switch (tapCount) {
        case 2:
            [self handleDoubleTapBegan:[touch locationInView:self.superview]];
            break;
        default:
            break;
    }
    [[self nextResponder] touchesEnded:touches withEvent:event];
}

- (void)handleDoubleTapBegan:(CGPoint)touchPoint {

    _doubleTapBeganPoint = touchPoint;

    NSLog(@"image double tap began at location: %@", NSStringFromCGPoint(touchPoint));
}

处理长按并使用 Y 坐标的差异来计算缩放比例。_minScale 存储您的初始缩放比例,以便我们可以恢复它。

- (void) imageLongPressed:(UIGestureRecognizer*)gesture {

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        self.maximumZoomScale = _maxScale * 2;
        self.minimumZoomScale = _minScale / 3;

        _longPressBeganPoint = [gesture locationInView:self.superview];

        [self setZoomScale:_minScale animated:YES];
        NSLog(@"image long press began at location: %@", NSStringFromCGPoint(_longPressBeganPoint));
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGPoint p = [gesture locationInView:self.superview];

        //NSLog(@"image long press changed at location: %@", NSStringFromCGPoint(p));

        if (CGPointEqualToPoint(_longPressBeganPoint, _doubleTapBeganPoint))
        {
            _zoom = _minScale + (p.y - _longPressBeganPoint.y) / 100.0;

            NSLog(@"zoom scale: %f", _zoom);

            [self setZoomScale:_zoom animated:NO];
        }
    }
    else if (gesture.state == UIGestureRecognizerStateEnded)
    {
        NSLog(@"image long press ended at location: %@", NSStringFromCGPoint([gesture locationInView:gesture.view]));

        if (self.zoomScale < _minScale)
        {
            [self setZoomScale:_minScale animated:YES];
            NSLog(@"min zoom scale: %f", _minScale);
        }
    }
}
于 2013-06-30T16:13:14.890 回答