2010-07-22 4 views
5

J'ai un UIView à l'intérieur d'un UIScrollView. Chaque fois que le zoom UIScrollView change, je souhaite redessiner l'intégralité du UIView au nouveau niveau de zoom.Redessiner UIScrollVoir le contenu après chaque zoom

Dans iOS 3.2 <, je faisais cela en redimensionnant la UIView dans le UIScrollView pour en faire la nouvelle taille, puis définir le Reprenez à l'identité, de sorte qu'il ne tenterait pas de redimensionner davantage. Cependant, avec iOS> = 3.2, la modification de l'identité modifie également la propriété zoomScale de UIScrollView.

Le résultat est que chaque fois que je zoome (disons 2x), j'ajuste le UIView intégré à la taille appropriée, et je le redessine. Cependant maintenant (depuis que j'ai réinitialisé la transformation à l'identité), le UIScrollView pense encore une fois à ZoomScale 1, plutôt que ZoomScale 2. Donc, si mon maxZoomScale est réglé sur 2, il va encore essayer de zoomer plus loin, ce qui est faux. J'ai pensé à utiliser le CATiledLayer, mais je ne pense pas que ce soit suffisant pour moi, puisque je veux redessiner après chaque zoom, pas seulement à certains seuils de zoom comme il essaie de le faire.

Est-ce que quelqu'un sait comment faire le redessin approprié du UIView sur un zoom?

Répondre

15

Tom,

Votre question est un peu vieux, mais je suis venu avec une solution pour cela, donc je me suis dit que je l'avais mis dans une réponse au cas où il vous aide ou quelqu'un d'autre. L'astuce consiste à réinitialiser la vue de défilement zoomScale à 1, puis à ajuster les minimumZoomScale et maximumZoomScale afin que l'utilisateur puisse toujours effectuer un zoom avant et arrière comme prévu.

Dans mon implémentation, j'ai sous-classé UIScrollView et l'ai défini comme étant son propre délégué. Dans ma sous-classe, j'implémente les deux méthodes de délégué dont vous avez besoin pour le zoom (voir ci-dessous). contentView est une propriété que j'ai ajoutée à ma sous-classe UIScrollView afin de lui donner l'affichage qui affiche réellement le contenu.

Alors, ma méthode init ressemble à quelque chose comme ça (kMinimumZoomScale et kMaximumZoomScale sont #define « s au sommet de la classe):

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     self.autoresizesSubviews = YES; 
     self.showsVerticalScrollIndicator = YES; 
     self.showsHorizontalScrollIndicator = NO; 
     self.bouncesZoom = YES; 
     self.alwaysBounceVertical = YES; 
     self.delegate = self; 

     self.minimumZoomScale = kMinimumZoomScale; 
     self.maximumZoomScale = kMaximumZoomScale; 
    } 

    return self; 
} 

Puis je mets en œuvre les méthodes standard UIScrollView de délégué pour le zoom. Ma classe ContentView possède une propriété appelée zoomScale qui lui indique l'échelle à utiliser pour afficher son contenu. Il l'utilise dans sa méthode drawRect pour redimensionner le contenu selon les besoins.

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView { 
    return contentView; 
} 


- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)scale { 
    CGFloat oldZoomScale = contentView.zoomScale; 
    CGSize size = self.bounds.size; 

    // Figure out where the scroll view was centered so that we can 
    // fix up its offset after adjusting the scaling 
    CGPoint contentCenter = self.contentOffset; 
    contentCenter.x += size.width/(oldZoomScale * scale)/2; 
    contentCenter.y += size.height/(oldZoomScale * scale)/2; 

    CGFloat newZoomScale = scale * oldZoomScale; 
    newZoomScale = MAX(newZoomScale, kMinimumZoomscale); 
    newZoomScale = MIN(newZoomScale, kMaximumZoomscale); 

    // Set the scroll view's zoom scale back to 1 and adjust its minimum and maximum 
    // to allow the expected amount of zooming. 
    self.zoomScale = 1.0; 
    self.minimumZoomScale = kMinimumZoomScale/newZoomScale; 
    self.maximumZoomScale = kMaximumZoomScale/newZoomScale; 

    // Tell the contentView about its new scale. My contentView.zoomScale setter method 
    // calls setNeedsDisplay, but you could also call it here 
    contentView.zoomScale = newZoomScale; 

    // My ContentView class overrides sizeThatFits to give its expected size with 
    // zoomScale taken into account 
    CGRect newContentSize = [contentView sizeThatFits]; 

    // update the content view's frame and the scroll view's contentSize with the new size 
    contentView.frame = CGRectMake(0, 0, newContentSize.width, newContentSize.height); 
    self.contentSize = newContentSize; 

    // Figure out the new contentOffset so that the contentView doesn't appear to move 
    CGPoint newContentOffset = CGPointMake(contentCenter.x - size.width/newZoomScale/2, 
              contentCenter.y - size.height/newZoomScale/2); 
    newContentOffset.x = MIN(newContentOffset.x, newContentSize.width - size.width); 
    newContentOffset.x = MAX(0, newContentOffset.x); 
    newContentOffset.y = MIN(newContentOffset.y, newContentSize.height - .size.height); 
    newContentOffset.y = MAX(0, newContentOffset.y); 
    [self setContentOffset:newContentOffset animated:NO]; 
} 
+0

Merci beaucoup pour votre solution! Cela résout [ma question] (http://stackoverflow.com/questions/3970988/how-to-draw-on-a-non-transformed-context-while-zoomed-in-a-catiledlayer). Pourriez-vous laisser un lien vers votre réponse là-bas, afin que je puisse vous donner le crédit nécessaire pour y répondre? – TinkerTank

+0

Si cette méthode est utilisée pour zoomer une CATiledLayer, le cache de tuiles doit être effacé avant d'appeler setNeedsDisplay. Une solution pour effacer le CATiledLayerCache est disponible [ici] (http: // stackoverflow.com/questions/1274680/clear-catiledlayers-cache-when-changement-images) – TinkerTank

+0

pouvez-vous s'il vous plaît expliquer la propriété de la contentSize et comment il se passe et ce qu'il est réellement. Je vous remercie – BDGapps

0

Dans mon cas, j'ai une vue de l'image et au-dessus de la vue de l'image que j'ai plusieurs autres imageviews. C'est la mise en œuvre que je suis venu avec et fonctionne bien:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(double)scale{ 
    NSLog(@"finished zooming"); 

    NSLog(@"position x :%f",pin1.frame.origin.x); 
    NSLog(@"position y :%f",pin1.frame.origin.y); 


    CGRect frame = pin1.frame; 
    frame.origin.x = pin1.frame.origin.x * scale; 
    frame.origin.y = pin1.frame.origin.y * scale; 
    pin1.frame = frame; 

    NSLog(@"position x new :%f",pin1.frame.origin.x); 
    NSLog(@"position y new:%f",pin1.frame.origin.y); 

} 
Questions connexes