2009-05-15 11 views
64

¿Cómo puedo averiguar el rect (CGRect) del contenido de una vista mostrada que es realmente visible en la pantalla.Obtener el rect visible de un contenido de UIScrollView

myScrollView.bounds 

El código anterior funciona cuando no hay una función de zoom, pero tan pronto como usted permite que el zoom, se rompe con el zoom escalas distinto de 1.

Para aclarar, yo quiero una CGRect que contiene el área visible de el contenido de la vista de desplazamiento, en relación con el contenido. (es decir, si es una escala de zoom 2, el tamaño del rect será la mitad del tamaño de la vista de desplazamiento, si está en la escala de zoom 0.5, será el doble.)

+5

Su pregunta se ha resuelto mi problema. ¡Estaba buscando el rect visible de scrollview! +1 para ti. –

Respuesta

80

responder a mi propia pregunta, sobre todo gracias a la respuesta de Jim Dovey, que no acababa de hacer el truco, pero me dio la base para mi respuesta:

CGRect visibleRect; 
visibleRect.origin = scrollView.contentOffset; 
visibleRect.size = scrollView.bounds.size; 

float theScale = 1.0/scale; 
visibleRect.origin.x *= theScale; 
visibleRect.origin.y *= theScale; 
visibleRect.size.width *= theScale; 
visibleRect.size.height *= theScale; 

La diferencia principal es que el tamaño de la visibleRect debe ser scrollView.bounds.size, en lugar de scrollView.contentSize, que es el tamaño de la vista de contenido. También simplificó un poco las matemáticas, y no vio el uso del isless() que rompería el código cada vez que fuera mayor.

+0

Esto parece fallar con iOS 3.2+, y CATiledLayer's - la zoomScale de scrollView siempre está configurada (por ejemplo en iPad:) "2.0" sin importar qué. Sé que UIScrollView fue cambiado en iOS 3.2. ¿Tal vez rompió esta solución? ¿O es CATiledLayer que lo rompe? Suspire – Adam

+0

ACTUALIZACIÓN: esto * funciona * con iOS 4+ - a menos que olvide implementar el método UIScrollViewDelegate "scrollViewDidEndZooming: withView: atScale:". NB: ¡el método puede estar vacío! Pero es un error de implementación de Apple que si el método no está allí ... Apple NO PODRÁ actualizar su propia propiedad de zoomScale (y quién sabe qué otros errores?) – Adam

+0

@kenneth Ballenegger ¿cuál es la "escala" (flotar theScale = 1.0/scale ;) en tu código? – Hitarth

0

No creo que UIScrollView te brinde ese rectángulo directamente, pero creo que tienes todos los elementos necesarios para calcularlo.

Una combinación de los límites, contentOffset y zoomScale debe ser todo lo que necesita para crear el rectángulo que está buscando.

25

Tienes que calcular usando propiedades contentOffset y contentSize de UIScrollView, así:

CGRect visibleRect; 
visibleRect.origin = scrollView.contentOffset; 
visibleRect.size = scrollView.contentSize; 

continuación, puede iniciar una sesión para la cordura de pruebas:

NSLog(@"Visible rect: %@", NSStringFromCGRect(visibleRect)); 

Para tener en cuenta el zoom (si esto ya no está hecho por la propiedad contentSize) necesitaría dividir cada coordenada por el zoomScale, o para un mejor rendimiento, lo multiplicaría por 1.0/zoomScale:

CGFloat scale = (CGFloat) 1.0/scrollView.zoomScale; 
if (isless(scale, 1.0))  // you need to #include <math.h> for isless() 
{ 
    visibleRect.origin.x *= scale; 
    visibleRect.origin.y *= scale; 
    visibleRect.size.width *= scale; 
    visibleRect.size.height *= scale; 
} 

Aparte: uso isless(), isgreater(), isequal() etc. de math.h porque estos (presumiblemente) harán lo correcto con respecto a los resultados de comparación en coma flotante 'no ordenados' y otras extrañas & maravillosa arquitectura casos de PF específicos.


Editar: Es necesario utilizar bounds.size en lugar de contentSize al calcular visibleRect.size.

+5

Creo que visibleRect.size = scrollView.frame.size; no contentSize)) – oxigen

+0

@property (no atómico) CGSize contentSize; // default CGSizeZero –

2
CGRect visibleRect; 
visibleRect.origin = scrollView.contentOffset; 
visibleRect.size = scrollView.frame.size; 
+1

Eso solo funciona con zoomScale = 1.0 –

99

O simplemente podría hacer la versión

CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:zoomedSubview]; 
+0

La mejor respuesta. El más corto y el más correcto. – n13

+7

¿Qué es zoomSubview? – zakdances

+2

zoomedSubview es la subvista por la que desea obtener el rect visible. – Trenskow

10

Shorter:

CGRect visibleRect = CGRectApplyAffineTransform(scrollView.bounds, CGAffineTransformMakeScale(1.0/scrollView.zoomScale, 1.0/scrollView.zoomScale)); 

No estoy seguro de si esto se define el comportamiento, pero casi todas las subclases UIView tener el origen de su bounds establecido a (0,0). UIScrollViews, sin embargo, tiene el origen configurado en contentOffset.

5

un poco de solución más general sería:

[scrollView convertRect:scrollView.bounds 
          toView:[scrollView.delegate viewForZoomingInScrollView:scrollView]]; 
Cuestiones relacionadas