web-dev-qa-db-fra.com

Comment faire un zoom avant/arrière sur une photo en tapant deux fois sur l'iPhone WWDC 2010 - 104 PhotoScroller

Je suis en train de parcourir l'exemple de code de l'application WWW 2010 - 104 PhotoScroller pour iPhone .. Il fonctionne parfaitement avec les images associées à mon projet (images de page PDF)

mais je me bats pour détecter des touches dans l'application PhotoScroller. Le zoom utilisant plusieurs touches est géré par ScrollVoiew. Maintenant, je veux agrandir/réduire la photo en tapotant deux fois. La méthode Touchesbegan est appelée dans TilingView Class. Ensuite, j'ai utilisé [super touchesbegan: withevent:] et maintenant les touches sont dans la classe ImageScrollView. 

Comment obtenir ces événements tactiles dans PhotoViewController . Comment réaliser le zoom avant et arrière sur le toucher? 

Quelqu'un peut-il aider à cet égard?

35
Roger_iPhone

J'ai fait des recherches sur plusieurs sites Web et j'ai proposé ce qui suit ...

Placez ce code dans votre méthode viewDidLoad ou viewWillAppear:

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

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

[doubleTap setNumberOfTapsRequired:2];

[self.scrollView addGestureRecognizer:doubleTap];

[doubleTap release];

Ajoutez ceci à votre fichier d'en-tête:

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

Ajoutez ceci à votre implémentation:

- (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]; 

  }  

Actuellement, cela ne concerne pas la zone où l'utilisateur a tapé deux fois.

68
geekinit

Mon code, basé sur une partie du code situé sur le lien " UIImageView ne fait pas de zoom " Ce code gère le basculement entre zoom avant et zoom arrière et permet la détection d'un tapé simultanément. Il centre également correctement le zoom sur l'image intégrée en appliquant la transformation de vue sur celle-ci. Ce code irait dans la classe ImageScrollView à partir de l'exemple de code.

- (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];
    }
}
65
possen

Voici une solution Swift basée sur la réponse de @ possen great.
- Placez ceci dans votre contrôleur de vue contenant le scrollview et son délégué.
- Cette solution est excellente car elle permet de zoomer sur l’emplacement du robinet:

@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
}
36
n8tr

J'ai combiné les réponses de @jayesh kavathiya et de @possen en une seule implémentation qui fonctionne plutôt bien, tant que vous avez défini les valeurs appropriées pour self.minimumZoomScale et 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];
    }
}
14

Swift 3

Normalement, la fonctionnalité de zoom image est requise avec un double tapotement et un geste de pincement, donc je fournis une solution complète pour atteindre le même objectif. Le zoom à double tap est inspiré des réponses ci-dessus et le zoom à pincement a été pris de ici .

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
    }

}
11
Akhilendra Singh

utilisez ce code pour zoomer là où vous cliquez .......

- (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;
        }
    } 

utilisez ce code pour zoomer là où vous avez cliqué ....... zoomChech est une variable booléenne pour vérifier le zoom 

3
jayesh kavathiya

La réponse précédente pourrait être plus simple avec BlocksKit , comme ci-dessous.

#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];
2
Tsuneo Yoshioka

Que diriez-vous d'ajouter un UITapGestureRecognizer à ImageScrollView?

Tant que vous consultez un exemple de code, vous pouvez vérifier comment UIGestureRecognizers est utilisé dans ScrollViewSuite .

1
wka

Zoom sur l'emplacement du robinet

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);
0
richy

Cela semble fonctionner avec convertRect:fromView: et 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];
}
0
jjrscott

Sous-classe UIScrollView et un fichier ajouté 

#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;
    }
}
0
Alex Terente

Vous devrez implémenter viewForZooming(in scrollView: UIScrollView) -> UIView? in UIScrollViewDelegate pour que la réponse de @ n8tr fonctionne.

 enter image description here

Donc, le code complet ressemblera à quelque chose comme ça

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
    }
}
0
Yasas Karunarathna