2010-03-05 3 views
5

La mia applicazione ha un UIScrollView con una sottoview. La sottoview è un UIView esteso che stampa a sé una pagina PDF usando i livelli nell'evento drawLayer.UIScrollView zoomToRect non esegue lo zoom su un valore specifico (creato da UITouch CGPoint)

Lo zoom utilizzando la presa integrata funziona alla grande. setZoomScale funziona anche come previsto.

Ho avuto problemi con la funzione zoomToRect. Ho trovato un esempio online che rende una variabile zoomRect di CGRect da un determinato CGPoint.

Nella funzione touchesEnded, se ci fosse un doppio tap e sono tutta la strada ingrandito, voglio per ingrandire a quella PDFUIView ho creato come se fossero pizzicando con il centro della pizzico in cui doppia sfruttato .

Quindi supporre che mi passa la variabile UITouch alla mia funzione che utilizza zoomToRect se Double Tap.

Ho iniziato con la seguente funzione che ho trovato su mele sito:

http://developer.apple.com/iphone/library/documentation/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html

La seguente è una versione modificata per la mia UIScrollView classe estesa:

- (void)zoomToCenter:(float)scale withCenter:(CGPoint)center {  

    CGRect zoomRect; 
    zoomRect.size.height = self.frame.size.height/scale; 
    zoomRect.size.width = self.frame.size.width/scale; 

    zoomRect.origin.x = center.x - (zoomRect.size.width/2.0); 
    zoomRect.origin.y = center.y - (zoomRect.size.height/2.0); 

    //return zoomRect; 

    [self zoomToRect:zoomRect animated:YES]; 

} 

Quando faccio questo, il UIScrollView sembra ingrandire usando il bordo in basso a destra dello zoomRetto sopra e non al centro.

Se faccio UIView come questo

UIView *v = [[UIView alloc] initWithFrame:zoomRect]; 
[v setBackgroundColor:[UIView redColor]]; 
[self addSubview:v]; 

La scatola rossa presenta con il punto di contatto morti nel centro.

Nota: lo sto scrivendo dal mio PC, ricordo di aver giocato con la parte divisa in due sul mio Mac, quindi supponiamo che questo disegni un rect con il punto di contatto al centro. Se l'UIView si è ritirato dal centro ma è stato ingrandito al punto giusto, sarebbe andato tutto bene.

Tuttavia, ciò che accade è quando la preforma zoomToRect sembra utilizzare basso a destra fuori zoomRect in alto a sinistra della ingrandita risultati.

Inoltre, ho notato che a seconda di dove clicco sul UIScrollView, àncora di differente macchie. Sembra quasi che ci sia una croce in mezzo e sta riflettendo i punti in qualche modo come se da qualche parte a sinistra del centro vi sia un riflesso negativo e ovunque nel mezzo c'è un riflesso positivo?

Questo sembra complicato, non dovrebbe solo lo zoom al rect che è stato disegnato come l'UIView è stato in grado di disegnare?

ho usato un sacco di ricerca per capire come creare un PDF in grado di scalare in alta qualità, così io parto dal presupposto che utilizzando il CALayer può essere gettando via il sistema di coordinate? Ma per UIScrollView dovrebbe trattarlo come una vista con dimensioni 768x985.

Questo è un po 'avanzato, si prega di assumere il codice per creare lo zoomRetto è tutto buono. C'è qualcosa di più profondo con il CALayer nella UIView che si trova in UIScrollView ....

risposta

0

Avevo qualcosa di simile ed è stato perché non ho regolato i valori center.x e center.y dividendoli per il scala anche (usando center.x/scale e center.y/scale). Forse non sto leggendo il tuo codice giusto.

0

Sto avendo lo stesso comportamento ed è piuttosto frustrante ... Il rettangolo che viene alimentato a UIScrollView è perfetto ... eppure il mio punto di vista, indipendentemente da quello che faccio qualsiasi cosa che comporti cambiando lo zoomScale a livello di programmazione sempre ingrandisce e ridimensiona a coordinare 0,0, non importa cosa.

Ho provato solo a cambiare lo zoomScale, ho provato a zoomToRect, li ho provati tutti, e ogni minuto nel momento in cui tocco lo zoomScale in codice, si passa a coordinate 0,0.

Ho anche dovuto aggiungere ed esplicitamente setContentSize all'immagine ridimensionata nella vista a scorrimento dopo un'operazione di zoom, o altrimenti non posso scorrere dopo uno zoom o un pizzico.

Si tratta di un bug in 3.1.3 o cosa?

1

Ho notato che la mela che stai utilizzando non esegue uno zoom corretto se l'immagine inizia con uno zoomScala meno di 1 perché l'origine di ZoomRetto non è corretta. L'ho modificato per funzionare correttamente. Ecco il codice:

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center { 

CGRect zoomRect; 

// the zoom rect is in the content view's coordinates. 
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds. 
// As the zoom scale decreases, so more content is visible, the size of the rect grows. 
zoomRect.size.height = [self frame].size.height/scale; 
zoomRect.size.width = [self frame].size.width/scale; 


// choose an origin so as to get the right center. 
zoomRect.origin.x = (center.x * (2 - self.minimumZoomScale) - (zoomRect.size.width/2.0)); 
zoomRect.origin.y = (center.y * (2 - self.minimumZoomScale) - (zoomRect.size.height/2.0)); 

return zoomRect; 
} 

La chiave è questa parte moltiplicando il valore centrale da (2 - self.minimumZoomScale). Spero che questo aiuti.

+0

ritardo commento, ma non ho potuto resistere; se funziona, è pura fortuna. Moltiplicare le coordinate di un centro non ha alcun significato. Se è necessario eseguire una traduzione su un centro, si aggiunge invece un valore. Ma molto probabilmente, il centro non è corretto perché è stato calcolato dal riferimento del sistema di coordinate sbagliato (ad esempio dalla vista errata) – jyavenard

0

Nel mio caso era:

zoomRect.origin.x = center.x/self.zoomScale - (zoomRect.size.width/2.0); 
zoomRect.origin.y = center.y/self.zoomScale - (zoomRect.size.height/2.0); 
4

Ok un'altra risposta:

La mela in dotazione lavori di routine per me, ma è necessario avere il sistema di riconoscimento gesto convertire il punto di rubinetto per le coordinate IMAGEVIEW - non allo scroller.

esempio di Apple fa questo, ma dal momento che la nostra applicazione funziona in modo diverso (si cambia l'UIImageView), in modo che il gestureRecongnizer è stato istituito l'UIScrollView - che funziona bene, ma è necessario farlo nel handleDoubleTap:

Questo è liberamente basato sul codice di esempio di Apple "TaptoZoom", ma come ho detto abbiamo bisogno del nostro riconoscitore di gesti collegato alla vista di scorrimento.

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer { 
    // double tap zooms in 
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleSingleTap:) object:nil]; 
    float newScale = [imageScrollView zoomScale] * 1.5; 
    // Note we need to get location of the tap in the imageView coords, not the imageScrollView 
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:imageView]]; 
    [imageScrollView zoomToRect:zoomRect animated:YES]; 
} 
+0

Grazie a @Tom, la conversione della posizione nella vista dell'immagine ha funzionato! – Motasim

+0

Questo è fantastico. Ha funzionato per me –

0

ho provato diverse soluzioni, ma questo sembra la migliore risoluzione E 'davvero semplice e concettuale?

CGRect frame = [[UIScreen mainScreen] applicationFrame]; 
scrollView.contentInset = UIEdgeInsetsMake(frame.size.height/2, 
       frame.size.width/2, 
       frame.size.height/2, 
       frame.size.width/2); 
0

Non sono d'accordo con uno dei commenti sopra dicendo che non si dovrebbe mai moltiplicare le coordinate del centro da parte di alcuni fattori.

Supponiamo che tu stia visualizzando un intero file 400x400px o file PDF in una visualizzazione di scorrimento 100x100 e desideri consentire agli utenti di raddoppiare le dimensioni del contenuto fino a 1: 1. Se si tocca due volte al punto (75,75), ci si aspetta che il rettangolo ingrandito abbia origine 100.100 e dimensioni 100x100 nella nuova vista del contenuto 200x200. Quindi il punto toccante originale (75,75) è ora (150,150) nel nuovo spazio 200x200.

Ora, dopo aver completato l'azione di zoom n. 1, se si tocca ancora due volte (75,75) all'interno del nuovo rettangolo 100x100 (che è il quadrato in basso a destra del rettangolo 200x200 più grande), si prevede che l'utente viene mostrato il 100x100 quadrato in basso a destra dell'immagine più grande, che ora diventerebbe ingrandito a 400x400 pixel.

Per calcolare l'origine di questo rettangolo 100x100 più recente all'interno del rettangolo 400x400 più grande, è necessario considerare la scala e l'offset del contenuto corrente (poiché prima dell'ultima azione di zoom veniva visualizzato il rettangolo 100x100 in basso a destra all'interno di un Rettangolo di contenuto 200x200).

Quindi la coordinata x del rettangolo finale diventa: center.x/currentScale - (scrollView.frame.size.width/2) + scrollView.contentOffset.x/currentScale = 75/0,5 - 100/2 + 100/.5 = 150 - 50 + 200 = 300.

In questo caso, essendo un quadrato, il calcolo per la coordinata y è lo stesso. E abbiamo effettivamente ingrandito il rettangolo 100x100 in basso a destra, che, nella più ampia vista del 400x400 ha origine 300.300.

Ecco come calcolare la dimensione e l'origine del rettangolo dello zoom: zoomRect.size.height = mScrollView.frame.size.height/scale; zoomRect.size.width = mScrollView.frame.size.width/scale;

zoomRect.origin.x = center.x/currentScale - (mScrollView.frame.size.width/2) + mScrollView.contentOffset.x/currentScale; 
zoomRect.origin.y = center.y/currentScale - (mScrollView.frame.size.height/2) + mScrollView.contentOffset.y/currentScale; 

Spero che questo abbia senso; è difficile spiegarlo per iscritto senza tracciare i vari quadrati/rettangoli.

Cheers, Raf Colasante

4
Declare BOOL isZoom; in .h 


    -(void)handleDoubleTap:(UIGestureRecognizer *)recognizer { 
      if(isZoom){ 
       CGPoint Pointview=[recognizer locationInView:self]; 
       CGFloat newZoomscal=3.0; 

       newZoomscal=MIN(newZoomscal, self.maximumZoomScale); 

       CGSize scrollViewSize=self.bounds.size; 

       CGFloat w=scrollViewSize.width/newZoomscal; 
       CGFloat h=scrollViewSize.height /newZoomscal; 
       CGFloat x= Pointview.x-(w/2.0); 
       CGFloat y = Pointview.y-(h/2.0); 

       CGRect rectTozoom=CGRectMake(x, y, w, h); 
       [self zoomToRect:rectTozoom animated:YES]; 

       [self setZoomScale:3.0 animated:YES]; 
       isZoom=NO; 
      } 
      else{ 
       [self setZoomScale:1.0 animated:YES]; 
       isZoom=YES; 
      } 
     }