2011-10-05 19 views
6

Mi sono guardato intorno e sembra che la gente dica che è possibile ri-renderizzare i dati dopo aver eseguito lo zoom in avanti ora che si conosce il fattore di scala per UIScrollView. Ho anche visto alcuni post su come rendere il tuo layer su CATiledLayer e impostare i livelli di OffDetailBias e levelsOfDetail.Rendere il contenuto dopo aver ingrandito UIScrollView

Quello che ho è un UIScrollView, e in essa, un ResultsView che è una sottoclasse di UIView:

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     CATiledLayer *tiledLayer = (CATiledLayer *)self.layer; 
     tiledLayer.levelsOfDetailBias = 3; 
     tiledLayer.levelsOfDetail = 3; 
     self.opaque = YES; 
    } 
    return self; 
} 

/* 
// Only override drawRect: if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
- (void)drawRect:(CGRect)rect 
{ 
    // Drawing code 
} 
*/ 

+ (Class)layerClass { 
    return [CATiledLayer class]; 
} 

Nella mia classe dove ho l'UIScrollView e ResultsView, lo faccio:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 
    return self.ResultsView; 
} 

È sufficiente avere il testo rerenderizzato (nitido)? O devo implementare qualcosa in

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { 
} 

Se è così, non sono sicuro di come farlo. Nella mia classe con UIScrollView e ResultsView, in ResultsView (nell'XIb), ho solo un paio di UILabels e Uiviews (le anteprime utilizzate per le intestazioni/i piè di pagina per la vista). Quindi non so come ridisegnare quelli da ResultsView. Sebbene ResultsView abbia UILabels e UIViews come figli nello XIB, non sono sicuro di come ridisegnerei quelli dalla classe ResultsView e cosa avrei comunque bisogno di fare.

O è questo l'approccio sbagliato? Devo semplicemente ridimensionare UILabel e UIView in base al fattore di scala nel metodo scrollViewDidEndZooming: delegate? TIA

risposta

18

Penso che tu stia prendendo l'approccio sbagliato. Se la tua vista è costituita da UILabels e UIViews che non eseguono alcun disegno personalizzato, non mi verrebbe in mente di utilizzare una vista di backup CATiledLayer. Invece implementare la scrollViewDidEndZooming: withView: atScale: metodo delegato e fare qualcosa di simile:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale { 
    scale *= [[[self.scrollView window] screen] scale]; 
    [view setContentScaleFactor:scale]; 
    for (UIView *subview in view.subviews) { 
     [subview setContentScaleFactor:scale]; 
    } 
} 
+0

grazie. Ha funzionato davvero bene. Non penso di aver trovato questo tipo di risposta da solo. Puoi spiegare perché hai bisogno della scala della prima riga * = ... Il valore che la finestra/schermo/scala restituisce è diverso per i dispositivi? Grazie. –

+0

Sì, questo rende compatibile il display retina. Su iPhone e iPod touch con display non Retina, la scala della schermata della finestra è 1.0, quindi non ha alcun effetto. Sui display retina è 2.0, quindi regola correttamente la scala per quei display. – afarnham

+0

Un approccio ancora più pulito potrebbe essere quello di rendere la vista che si sta ingrandendo una sottoclasse di UIView (se non lo è già) e creare un metodo che dice ad ogni subview di aggiornarlo contentScaleFactor direttamente anziché eseguire il ciclo di tutte le sottoview. Ti darebbe un controllo più accurato se hai alcune sottoview che fanno disegni personalizzati, come vorresti chiamare anche setNeedsDisplay. – afarnham

4

devo qualcosa di piccolo da aggiungere alla soluzione accettata che mi ha causato qualche minuto di dolore nel caso in cui nessun altro corre in stessa cosa.

Attraverso tutte le visualizzazioni secondarie nella vista che si sta eseguendo lo zoom e chiamando setContentScaleFactor non viene preso in considerazione se una delle sottoview dispone di sottoview. Se si dispone di una configurazione più complessa come quella, assicuratevi di anche un ciclo tra i subviews di quelle viste container e chiamare

[subview setContentScaleFactor:scale]; 

su ciascuno. Ho creato un metodo che posso invocare per chiamare setContentScaleFactor su tutte le sottoview di una determinata vista e chiamarlo per ogni "vista del contenitore" sullo schermo.

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale 
{ 
    scale *= [[[self.scrollView window] screen] scale]; 
    [view setContentScaleFactor:scale]; 
    for (UIView *subview in view.subviews) 
    { 
     [self setContentSizeForView:subview andScore:scale]; 

     //Loop through all the subviews inside the subview 
     for(UIView *subSubview in subview.subviews) 
     { 
      [self setContentSizeForView:subSubview andScale:scale]; 
     } 
    } 
} 

- (void) setContentSizeForView:(UIView*) view andScale:(float)scale 
{ 
    [view setContentScaleFactor:scale]; 
} 
+0

Devo fare altre chiamate?Quando imposto il contentScaleFactor della mia sottoclasse UIView (la vista è utilizzata per il disegno e per lo zoom) uguale al valore della scala (del metodo delegato UIScrollView) la mia app diventa molto lenta e si blocca. – Sebastian

+0

Sì, ho anche notato che si tratta di un'operazione molto lenta quando ci sono molte sottoview. Alla fine ho rinunciato a migliorare la nitidezza del contenuto mentre eseguivo lo zoom per una complessa vista/gerarchia di sottomenu poiché era troppo lento. – DiscDev

+0

perché non si incolla il metodo che hai fatto? –

Problemi correlati