2009-05-15 17 views
64

Come posso fare per trovare il rect (CGRect) del contenuto di una vista visualizzata che in realtà è visibile sullo schermo.Ottenere il rettangolo visibile del contenuto di un UIScrollView

myScrollView.bounds 

Il codice sopra funziona quando non c'è lo zoom, ma non appena si permettono lo zoom, si rompe a scale di zoom diverso da 1.

Per chiarire, io voglio un CGRect che contiene l'area visibile di il contenuto della vista di scorrimento, relativo al contenuto. (ad esempio se si tratta di una scala di zoom 2, la dimensione del rect sarà metà della dimensione della vista di scorrimento, se è a scala 0.5, sarà doppia.)

+5

La tua domanda si è risolto il mio problema. Stavo cercando il rect visibile di scrollview! +1 per te. –

risposta

80

Rispondendo alla mia domanda, per lo più grazie alla risposta di Jim Dovey, che non riusciva a fare il trucco, ma mi ha dato la base per la mia risposta:

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 differenza principale è che la dimensione della visibleRect dovrebbe essere scrollView.bounds.size, anziché scrollView.contentSize, che è la dimensione della visualizzazione del contenuto. Semplificato anche un po 'la matematica, e non ho visto abbastanza l'uso per lo isless() che avrebbe rotto il codice ogni volta che è maggiore.

+0

Questo sembra non funzionare con iOS 3.2+, e CATiledLayer's - lo zoomScale di scrollView è sempre impostato su (ad esempio su iPad:) "2.0", a prescindere da cosa. So che UIScrollView è stato modificato in iOS 3.2 - forse ha rotto questa soluzione alternativa? O è CATiledLayer che lo spezza? Sigh – Adam

+0

UPDATE: questo * funziona * con iOS 4+ - a meno che non si dimentichi di implementare il metodo UIScrollViewDelegate "scrollViewDidEndZooming: withView: atScale:". NB: il metodo può essere vuoto! Ma è un bug di implementazione di Apple che se il metodo non è lì ... Apple non aggiorna la propria proprietà zoomScale (e chissà quali altri bug?) – Adam

+0

@kenneth Ballenegger qual è la "scala" (float theScale = 1.0/scale ;) nel tuo codice? – Hitarth

0

Non penso che un UIScrollView ti dia quel rettangolo direttamente, ma penso che tu abbia tutti gli elementi necessari per calcolarlo.

Una combinazione di limiti, contentOffset e zoomScale dovrebbe essere tutto ciò che serve per creare il rettangolo che si sta cercando.

25

dovete calcolare utilizzando le proprietà contentOffset e contentSize di UIScrollView, in questo modo:

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

È possibile quindi accedere per sanity-test:

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

Per rappresentano lo zoom (se questo non è già stato fatto dalla proprietà contentSize) avresti bisogno di dividere ogni coordinata per lo zoomScale, o per prestazioni migliori che moltiplicheresti per 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; 
} 

A parte: io uso isless(), isgreater(), isequal() ecc. Da math.h perché questi (presumibilmente) fanno la cosa giusta per quanto riguarda i risultati di confronto a virgola mobile "non ordinati" e altre strane architetture & - casi specifici di FP


Edit: È necessario utilizzare bounds.size invece di contentSize nel calcolo visibleRect.size.

+5

Penso che visibleRect.size = scrollView.frame.size; non contentSize)) – oxigen

+0

@property (nonatomic) CGSize contentSize; // default CGSizeZero –

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

Funziona solo con zoomScale = 1.0 –

99

Oppure si potrebbe semplicemente fare versione

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

Risposta migliore. Il più breve e il più corretto. – n13

+7

cosa viene ingranditoSubview? – zakdances

+2

zoomedSubview è la sottoview che non vorresti ottenere per il rect visibile. – Trenskow

10

Shorter:

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

Non sono sicuro se questo viene definito comportamento, ma quasi tutte le sottoclassi UIView avere l'origine della loro bounds impostato su (0,0). Le viste UIScroll, tuttavia, hanno l'origine impostata su contentOffset.

5

un po 'di soluzione più generale potrebbe essere:

[scrollView convertRect:scrollView.bounds 
          toView:[scrollView.delegate viewForZoomingInScrollView:scrollView]]; 
Problemi correlati