2010-01-25 10 views
4

J'ai essayé d'implémenter le zoom/entrée de pincement pour PhotoView (une instance de UIImageView) en utilisant CGAffinTransformScale (en planifiant d'utiliser la rotation, donc je ne peux pas compter sur les images pour le zoom et ajouter des sous-vues plus compliqué, je pense). Quoi qu'il en soit, le concept était assez facile à saisir et le code s'est réuni très rapidement ... Depuis, j'ai essayé de résoudre les deux mêmes problèmes (liés ?!), en utilisant trois approches différentes, et je n'ai pas pu le faire : 1- Mon code perd en quelque sorte la trace du nombre de touches au milieu du zoom, de compte = 2 à compte = 1 et de retour sur l'iPhone, mais pas le simulateur. 2- Les points de contact un et deux continuent à faire des va-et-vient de quelques pixels à chaque mouvement, provoquant le rétrécissement et l'agrandissement de l'image successivement et rapidement, même si globalement l'effet est de zoomer ou zoomer à la fois iPhone et simulateur).iPhone UIImageView pincer zoom

est ici le code:

#import "PhotoView.h" 


@implementation PhotoView; 
@synthesize originalCenter, distance, zooming; 
- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
    // Initialization code 
     self.userInteractionEnabled = YES; 
     self.multipleTouchEnabled = YES; 
     zooming = NO; 
    } 
    return self; 
} 

float distanceBetweenTwoPoints(CGPoint point1, CGPoint point2) 
{ 
NSLog(@"point1 x: %5.2f point 2 x: %5.2f ---- point 1 y: %5.2f point 2 y: %5.2f",point1.x,point2.x,point1.y,point2.y); 
    return (sqrt(pow(point1.x -point2.x,2) + pow(point1.y - point2.y,2))); 
} 
-(void) touchesBegan: (NSSet *) touches withEvent:(UIEvent *) event { 

    if ([touches count] > 1) { 

     NSLog(@"^^^^^^^^^^^^^^^Tocuhes began with double touch!"); 

     distance = distanceBetweenTwoPoints([[[touches allObjects] objectAtIndex:0] locationInView:self], 
     [[[touches allObjects] objectAtIndex:1] locationInView:self]); 
     zooming = YES; 
    } 
    else { 
     zooming = NO; 
     origianlCenter = [[[touches allObjects] objectAtIndex:0] locationInView:self]; 
     NSLog(@">>>>>>>>>>>>Touches began with single touch"); 
    } 
} 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    if (zooming) NSLog(@"!!!!!!!!!end zoom!!!!!!!"); 

    zooming = NO; 
    if ([[touches anyObject] tapCount] == 2) { 
     UITouch *thisTouch = [touches anyObject]; 
     CGPoint thisPoint = [thisTouch locationInView:self]; 
    } 
} 

- (void) touchesMoved: (NSSet *) touches withEvent:(UIEvent *) event { 
    if ([touches count] > 1 && zooming) { // ignore if user added a second finger touch 
     float distanceNew = distanceBetweenTwoPoints([[[touches allObjects] objectAtIndex:0]  locationInView:self], 
       [[[touches allObjects] objectAtIndex:1] locationInView:self]); 
     if (distance <= 0.f) { // should never be true - but it is sometimes!!! 
      distance = distanceNew; 
     } 
     float delta = 1.0f + ((distanceNew-distance)/distance); 
     self.transform = CGAffineTransformScale(self.transform, delta, delta); 
     distance = distanceNew; 
    } 
    else { 
     if (zooming) { 
      NSLog(@"*************shouldn't be here********* %d",[touches count]); 
      return; 
     } 
     CGPoint thisPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self]; 
     self.transform = CGAffineTransformTranslate(self.transform, thisPoint.x-originalCenter.x, thisPoint.y-originalCenter.y); 

    } 
} 
- (void)dealloc { 
    [super dealloc]; 
} 
@end 

L'échantillon de journal:

^^^^^^^^^^^^^^^Tocuhes began with double touch! 
point1 x: 87.33 point 2 x: 235.63 ---- point 1 y: 322.30 point 2 y: 117.09 
point1 x: 90.76 point 2 x: 232.02 ---- point 1 y: 318.29 point 2 y: 123.51 
point1 x: 86.22 point 2 x: 236.71 ---- point 1 y: 323.30 point 2 y: 117.42 
point1 x: 89.51 point 2 x: 232.38 ---- point 1 y: 319.47 point 2 y: 123.47 
point1 x: 84.97 point 2 x: 237.02 ---- point 1 y: 324.48 point 2 y: 116.56 
*************shouldn't be here********* 1 
point1 x: 88.49 point 2 x: 232.52 ---- point 1 y: 321.27 point 2 y: 122.91 
*************shouldn't be here********* 1 
point1 x: 83.95 point 2 x: 237.11 ---- point 1 y: 327.21 point 2 y: 116.96 
!!!!!!!!!end zoom!!!!!!! 

Je commence à croire que je suis en train de perdre la trace des points de contact en raison de CGAffinTransformScale; Cependant, je n'ai rien trouvé en ligne pour suggérer que cela soit un problème. Tous les indices (y compris «lire la documentation sur xyz») seraient appréciés!

Merci d'avance.

Répondre

6

De manière générale, chaque fois que vous implémentez un comportement d'interface utilisateur continu, vous devez le mesurer par rapport à un élément qui ne change pas. Par conséquent, si vos touches entraînent une modification de la transformation de vue, vous devez mesurer les contacts par rapport à un élément qui ne change pas: votre vue parent par exemple. Ainsi, au lieu d'appeler:

[touch locationInView:self] 

vous devez utiliser

[touch locationInView:[self superview]] 

Je ne sais pas si cela va résoudre votre problème, mais il permettra d'éliminer une des causes possibles de vos problèmes.

+0

C'était tout !!! Merci beaucoup. – cameron

17

Une réponse du champ gauche peut-être, mais une alternative pourrait être de placer le UIImageView dans un UIScrollView, définir une méthode viewForZoomingInScrollView: sur votre délégué de vue de défilement, et définissez les propriétés maximumZoomScale/minimumZoomScale et vous aurez votre pincée zoomer sans avoir besoin d'implémenter les calculs pour définir vous-même la transformation? Je viens de le faire sur un projet récent et ça a bien marché.

+0

Oui ... environ mille fois plus facile que l'inverse. Merci! – glenc

+0

Apple a une bonne documentation sur cette technique: http://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html – Stickley