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?
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.
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];
}
}
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
}
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];
}
}
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
}
}
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
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];
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 .
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);
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];
}
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;
}
}
Vous devrez implémenter viewForZooming(in scrollView: UIScrollView) -> UIView? in UIScrollViewDelegate
pour que la réponse de @ n8tr fonctionne.
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
}
}