2010-07-22 18 views
5

Tengo UIView dentro de UIScrollView. Cada vez que cambie el zoom UIScrollView, deseo volver a dibujar el UIView completo en el nuevo nivel de zoom.Redibujar UIScrollVer contenido después de cada zoom

En iOS 3.2 <, yo estaba haciendo esto cambiando el tamaño del UIView dentro del UIScrollView para que sea el nuevo tamaño, y luego poner la transformada de nuevo a la identidad, por lo que no sería tratar de cambiar su tamaño más. Sin embargo, con iOS> = 3.2, cambiar la identidad también cambia la propiedad zoomScale de UIScrollView.

El resultado es que siempre que hago zoom (digamos 2x), ajusto el UIView incrustado para que tenga el tamaño apropiado y lo vuelvo a dibujar. Sin embargo, ahora (desde que reinicié la transformación a Identidad), el UIScrollView piensa que es una vez más en zoomScale 1, en lugar de zoomScale 2. Por lo tanto, si mi maxZoomScale está configurado en 2, se seguirá intentando ampliar, lo cual es incorrecto.

Pensé en usar el CATiledLayer, pero no creo que esto sea suficiente para mí, ya que quiero volver a dibujar después de cada acercamiento, no solo a ciertos umbrales de acercamiento como lo intenta hacer.

¿Alguien sabe cómo hacer el rediseño correcto de UIView con un zoom?

Respuesta

15

Tom,

Su pregunta es un poco viejo, pero se le ocurrió una solución para esto, así que pensé que había puesto en una respuesta en caso de que usted o cualquier otra ayuda. El truco básico es restablecer zoomScale de la vista de desplazamiento a 1, y luego ajustar minimumZoomScale y maximumZoomScale para que el usuario pueda acercar y alejar como se esperaba.

En mi implementación, he subclasificado UIScrollView y lo configuré para que sea su propio delegado. En mi subclase, implemento los dos métodos de delegado que necesita para ampliar (se muestra a continuación). contentView es una propiedad que agregué a mi subclase UIScrollView para darle la vista que realmente muestra el contenido.

lo tanto, mi método init se ve algo como esto (y kMinimumZoomScalekMaximumZoomScale son #define 's en la parte superior de la clase):

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

Entonces implementar los métodos de delegado UIScrollView estándar para el zoom. Mi clase ContentView tiene una propiedad llamada zoomScale que le dice qué escala usar para mostrar su contenido. Lo usa en su método drawRect para cambiar el tamaño del contenido según corresponda.

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

¡Muchas gracias por su solución! Esto resuelve [mi pregunta] (http://stackoverflow.com/questions/3970988/how-to-draw-on-a-non-transformed-context-while-zoomed-in-a-catiledlayer). ¿Podría dejar un enlace a su respuesta allí, para que pueda darle el crédito adecuado por responderla? – TinkerTank

+0

Si este método se utiliza para acercar o alejar un CATiledLayer, la memoria caché de teselas debe borrarse antes de llamar a setNeedsDisplay. Una solución para borrar el CATiledLayerCache está disponible [aquí] (http: // stackoverflow.com/preguntas/1274680/claros-catiledlayers-cache-when-cambiantes imágenes secundarias) – TinkerTank

+0

pueden explicar por favor la propiedad del contentSize y cómo se consigue el sistema y lo que realmente es. Gracias – BDGapps

0

En mi caso, tengo una vista de imagen y en la parte superior de la vista de imagen tengo varias otras vistas de imagen. Esta es la implementación que se me ocurrió y funciona 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); 

} 
Cuestiones relacionadas