44

我正在浏览 iPhone WWDC 2010 - 104 PhotoScroller App 的示例代码。它适用于我的项目相关图像(PDF 页面图像)

但我正在努力检测 PhotoScroller 应用程序中的触摸。使用多个触摸的缩放由 ScrollVoiew 处理。现在我想在双击时放大/缩小照片。在 TilingView 类中调用 Touchesbegan 方法。然后我使用 [super touchesbegan: withevent:] 现在触摸在 ImageScrollView 类中。

如何在 PhotoViewController 中获取这些触摸事件。如何实现触摸放大和缩小?

任何人都可以在这方面提供帮助吗?

4

14 回答 14

71

我研究了几个不同的网站,我想出了以下...

将此代码放入您的 viewDidLoad 或 viewWillAppear 方法中:

//////////////////////////////
// Listen for Double Tap Zoom

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];

[doubleTap setNumberOfTapsRequired:2];

[self.scrollView addGestureRecognizer:doubleTap];

[doubleTap release];

将此添加到您的头文件中:

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer;

将此添加到您的实现中:

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {  

    if(self.scrollView.zoomScale > self.scrollView.minimumZoomScale)
        [self.scrollView setZoomScale:self.scrollView.minimumZoomScale animated:YES]; 
    else 
        [self.scrollView setZoomScale:self.scrollView.maximumZoomScale animated:YES]; 

  }  

目前,这并不以用户双击的区域为中心。

于 2011-11-28T21:57:55.383 回答
65

我的代码,基于链接“ UIImageView 不缩放”中的一些代码 此代码处理放大和缩小之间的切换,并允许检测单击和双击。它还通过在其上应用视图变换正确地将缩放集中在嵌入图像上。此代码将进入示例代码中的 ImageScrollView 类。

- (void)setupGestureRecognisers:(UIView *)viewToAttach {

    UITapGestureRecognizer *dblRecognizer;
    dblRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                        action:@selector(handleDoubleTapFrom:)];
    [dblRecognizer setNumberOfTapsRequired:2];

    [viewToAttach addGestureRecognizer:dblRecognizer];
    self.doubleTapRecognizer = dblRecognizer;

    UITapGestureRecognizer *recognizer;
    recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                     action:@selector(handleTapFrom:)];
    [recognizer requireGestureRecognizerToFail:dblRecognizer];

    [viewToAttach addGestureRecognizer:recognizer];
    self.tapRecognizer = recognizer;
}

- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {

   // do your single tap
}


- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {

    CGRect zoomRect;

    zoomRect.size.height = [_imageView frame].size.height / scale;
    zoomRect.size.width  = [_imageView frame].size.width  / scale;

    center = [_imageView convertPoint:center fromView:self];

    zoomRect.origin.x    = center.x - ((zoomRect.size.width / 2.0));
    zoomRect.origin.y    = center.y - ((zoomRect.size.height / 2.0));

    return zoomRect;
}

- (void)handleDoubleTapFrom:(UITapGestureRecognizer *)recognizer {

    float newScale = [self zoomScale] * 4.0;

    if (self.zoomScale > self.minimumZoomScale)
    {
        [self setZoomScale:self.minimumZoomScale animated:YES]; 
    }
    else 
    {
        CGRect zoomRect = [self zoomRectForScale:newScale 
                                   withCenter:[recognizer locationInView:recognizer.view]];
        [self zoomToRect:zoomRect animated:YES];
    }
}
于 2012-06-12T19:13:29.953 回答
40

这是一个基于@possen出色答案的Swift解决方案。 - 将它放在包含滚动视图并且是滚动视图委托的视图控制器中。 - 这个解决方案很棒,因为它实际上会缩放到点击位置:

@IBAction func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
    if scrollView.zoomScale == 1 {
        scrollView.zoom(to: zoomRectForScale(scale: scrollView.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
    } else {
        scrollView.setZoomScale(1, animated: true)
    }
}

func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
    var zoomRect = CGRect.zero
    zoomRect.size.height = imageView.frame.size.height / scale
    zoomRect.size.width  = imageView.frame.size.width  / scale
    let newCenter = scrollView.convert(center, from: imageView)
    zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
    zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
    return zoomRect
}
于 2015-11-21T00:48:35.367 回答
20

斯威夫特 3

通常,双击和捏合手势都需要图像缩放功能,因此我提供了完整的解决方案来实现相同的功能。双击缩放受上述答案的启发,捏缩放取自此处

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    var imageView: UIImageView!
    var scrollImg: UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let vWidth = self.view.frame.width
        let vHeight = self.view.frame.height

        scrollImg = UIScrollView()
        scrollImg.delegate = self
        scrollImg.frame = CGRect(x: 0, y: 0, width: vWidth, height: vHeight)
        scrollImg.backgroundColor = UIColor(red: 90, green: 90, blue: 90, alpha: 0.90)
        scrollImg.alwaysBounceVertical = false
        scrollImg.alwaysBounceHorizontal = false
        scrollImg.showsVerticalScrollIndicator = true
        scrollImg.flashScrollIndicators()

        scrollImg.minimumZoomScale = 1.0
        scrollImg.maximumZoomScale = 10.0

        let doubleTapGest = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTapScrollView(recognizer:)))
        doubleTapGest.numberOfTapsRequired = 2
        scrollImg.addGestureRecognizer(doubleTapGest)

        self.view.addSubview(scrollImg)

        imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: vWidth, height: vHeight))
        imageView.image = UIImage(named: "cat")
        imageView!.layer.cornerRadius = 11.0
        imageView!.clipsToBounds = false
        scrollImg.addSubview(imageView!)
    }

    func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
        if scrollImg.zoomScale == 1 {
            scrollImg.zoom(to: zoomRectForScale(scale: scrollImg.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
        } else {
            scrollImg.setZoomScale(1, animated: true)
        }
    }

    func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
        var zoomRect = CGRect.zero
        zoomRect.size.height = imageView.frame.size.height / scale
        zoomRect.size.width  = imageView.frame.size.width  / scale
        let newCenter = imageView.convert(center, from: scrollImg)
        zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
        zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
        return zoomRect
    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return self.imageView
    }

}
于 2017-09-10T17:23:05.103 回答
15

我将@jayesh kavathiya 和@possen 的答案组合成一个运行良好的实现,只要您为self.minimumZoomScaleand设置了适当的值self.maximumZoomScale

- (void)doubleTap:(UITapGestureRecognizer*)recognizer
{
    if (self.zoomScale > self.minimumZoomScale)
    {
        [self setZoomScale:self.minimumZoomScale animated:YES];
    }
    else
    {
        CGPoint touch = [recognizer locationInView:recognizer.view];

        CGSize scrollViewSize = self.bounds.size;

        CGFloat w = scrollViewSize.width / self.maximumZoomScale;
        CGFloat h = scrollViewSize.height / self.maximumZoomScale;
        CGFloat x = touch.x-(w/2.0);
        CGFloat y = touch.y-(h/2.0);

        CGRect rectTozoom=CGRectMake(x, y, w, h);
        [self zoomToRect:rectTozoom animated:YES];
    }
}
于 2013-10-02T20:45:14.343 回答
3

使用此代码,它会在您单击的位置缩放.......

- (void)handleDoubleTap:(UIGestureRecognizer *)recognizer {  
        if(zoomCheck){
            CGPoint Pointview=[recognizer locationInView:self];
            CGFloat newZoomscal=3.0;

            newZoomscal=MIN(newZoomscal, self.maximumZoomScale);

            CGSize scrollViewSize=self.bounds.size;

            CGFloat w=scrollViewSize.width/newZoomscal;
            CGFloat h=scrollViewSize.height /newZoomscal;
            CGFloat x= Pointview.x-(w/2.0);
            CGFloat y = Pointview.y-(h/2.0);

            CGRect rectTozoom=CGRectMake(x, y, w, h);
            [self zoomToRect:rectTozoom animated:YES]; 

            [self setZoomScale:3.0 animated:YES]; 
            zoomCheck=NO;
        }
        else{ 
            [self setZoomScale:1.0 animated:YES]; 
            zoomCheck=YES;
        }
    } 

使用此代码,它会在您单击的位置缩放....... zoomChech 是用于检查缩放的布尔变量

于 2012-09-05T14:44:24.980 回答
2

使用BlocksKit之前的答案可能会更简单,如下所示。

#import "BlocksKit.h"
...
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
    if(scrollView.zoomScale != 1.0){
        [scrollView setZoomScale:1.0 animated:YES];
    }else{
        [scrollView setZoomScale:2.0 animated:YES];
    }
}];
[doubleTap setNumberOfTapsRequired:2];
[scrollView addGestureRecognizer:doubleTap];
于 2012-12-14T15:11:33.643 回答
2

您需要实施viewForZooming(in scrollView: UIScrollView) -> UIView? in UIScrollViewDelegate才能使@n8tr 的答案正常工作。

在此处输入图像描述

所以完整的代码看起来像这样

class ViewController: UIViewController, UIScrollViewDelegate {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var imageView: UIImageView!


    override func viewDidLoad() {
        super.viewDidLoad()

        scrollView.delegate = self
    }

    @IBAction func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
        if scrollView.zoomScale == 1 {
            scrollView.zoom(to: zoomRectForScale(scale: scrollView.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
        } else {
            scrollView.setZoomScale(1, animated: true)
        }
    }

    func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
        var zoomRect = CGRect.zero
        zoomRect.size.height = imageView.frame.size.height / scale
        zoomRect.size.width  = imageView.frame.size.width  / scale
        let newCenter = imageView.convert(center, from: scrollView)
        zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
        zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
        return zoomRect
    }


    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return imageView
    }
}
于 2017-09-10T09:43:33.760 回答
2

它是 swift 5 的最新代码,用于双指缩放和双击缩放。

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var imageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()
    scrollView.delegate = self

    let doubleTapGest = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTapScrollView(recognizer:)))
    doubleTapGest.numberOfTapsRequired = 2
    scrollView.addGestureRecognizer(doubleTapGest)
}

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView
}

@objc func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
    if scrollView.zoomScale == 1 {
        scrollView.zoom(to: zoomRectForScale(scale: scrollView.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
    }
    else {
        scrollView.setZoomScale(1, animated: true)
    }
}

func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
    var zoomRect = CGRect.zero
    zoomRect.size.height = imageView.frame.size.height / scale
    zoomRect.size.width  = imageView.frame.size.width  / scale
    let newCenter = imageView.convert(center, from: scrollView)
    zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
    zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
    return zoomRect
}


}

我也附上了故事板图片。

在此处输入图像描述

于 2019-05-17T06:08:18.753 回答
1

将 UITapGestureRecognizer 添加到 ImageScrollView 怎么样?

只要你在看示例代码,就可以查看ScrollViewSuite 示例代码中 UIGestureRecognizers 是如何使用的。

于 2010-10-20T02:16:49.783 回答
0

在 m 文件中添加 UIScrollView 的子类

#pragma mark -
#pragma mark doubleTouch

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    NSUInteger tapCount = [touch tapCount];
    switch (tapCount) {
        case 2:
        {
            if(self.zoomScale <1.0){
                [self setZoomScale:1.0 animated:YES];
            }else{
                [self setZoomScale:0.1 animated:YES];
            }

            break;
        }
        default:
            break;
    }
}
于 2011-01-07T14:17:08.157 回答
0

这似乎可以使用convertRect:fromView:and工作zoomToRect:animated:

-(void)tap:(UITapGestureRecognizer *)tapGestureRecognizer
{
    CGFloat zoomeScaleMultiplier = 0.5;
    UIScrollView *scrollView = (UIScrollView *) tapGestureRecognizer.view;
    UIView *zoomableView = [scrollView.delegate viewForZoomingInScrollView:scrollView];

    CGRect rect = scrollView.bounds;
    rect.origin = CGPointZero;

    CGAffineTransform transform = CGAffineTransformMakeScale(zoomeScaleMultiplier, zoomeScaleMultiplier);
    rect = CGRectApplyAffineTransform(rect, transform);

    rect.origin = [tapGestureRecognizer locationInView:scrollView];

    rect = CGRectOffset(rect, CGRectGetWidth(rect)/-2., CGRectGetHeight(rect)/-2.);

    rect = [zoomableView convertRect:rect fromView:scrollView];

    [scrollView zoomToRect:rect animated:YES];
}
于 2014-08-30T21:46:43.067 回答
0

放大点击位置

CGFloat scale = 3.0;
CGFloat scale = ScaleToAspectFitRectAroundRect(frame, self.bounds) * 2.0;

CGRect zoomRect;
CGPoint point = [gestureRecognizer locationOfTouch:0 inView:[gestureRecognizer view]];

zoomRect.size.height = frame.size.height * scale;
zoomRect.size.width  = frame.size.width  * scale;

zoomRect.origin.x = CGRectGetMidX(frame) - (CGRectGetWidth(zoomRect)/2) + (scale * (CGRectGetWidth(frame)/2 - point.x)) - (CGRectGetWidth(frame)/2 - point.x);
zoomRect.origin.y = CGRectGetMidY(frame) - (CGRectGetHeight(zoomRect)/2) + (scale * (CGRectGetHeight(frame)/2 - point.y)) - (CGRectGetHeight(frame)/2 - point.y);
于 2015-04-10T11:43:38.717 回答
-1

这里我的代码对我有用,很简单:

// Listen for Double Tap Zoom
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];

[doubleTap setNumberOfTapsRequired:2];

[self addGestureRecognizer:doubleTap];

你需要

BOOL checkZoomImage;

这里选项卡方法

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {

    if (self.zoomScale > self.minimumZoomScale && self.zoomScale == self.maximumZoomScale){
        checkZoomImage = YES;
    }
    if (self.zoomScale < self.maximumZoomScale && self.zoomScale == self.minimumZoomScale) {
        checkZoomImage = NO;
    }


    if (checkZoomImage) {
        [self setZoomScale:self.zoomScale *0.5 animated:YES];
    }else{
        [self setZoomScale:self.zoomScale *1.5 animated:YES];
    }

}
于 2015-07-23T09:31:15.310 回答